9

I first thought about SED (sed "s/^/COUNTER \&/" /tmp/1.tex) but it is designed for a single line, and I cannot increment the counter itself by sed so thinking now awk because I have great experiences with gawk in integrated approaches. Data

What & South Dragon & North Dragon    & 5 \\ \hline
What & South Dragon & North Dragon    & 5 \\ \hline
What & South Dragon & North Dragon    & 5 \\ \hline

Expected output

1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

OS: Debian 8.5

11

nl is a utility to number the lines of a file.Usage:

nl /path/to/file

In your specific case:

$ nl  -s ' & ' input.txt                                                                                                 
     1 & What & South Dragon & North Dragon    & 5 \\ \hline
     2 & What & South Dragon & North Dragon    & 5 \\ \hline
     3 & What & South Dragon & North Dragon    & 5 \\ \hline
  • How can you combine this with preappending counter and the ampersand? - - It works for the counter, but not sure if also for the latter. – Léo Léopold Hertz 준영 Dec 27 '16 at 20:38
  • 3
    nl -s ' &' /path/to/file. -s specifies what separates the numbers from the body of the input file. – DopeGhoti Dec 27 '16 at 20:40
  • 1
    nl differs from cat -n and the awk solution in that it does not number empty lines by default – iruvar Dec 27 '16 at 20:58
10

This achieves what you're after. (as does awk '$0=NR" & "$0' filename, but that's a bit cryptic)

awk '{print NR,"&",$0}' filename
1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

Or if sed preferable, this gives same result.

sed = filename | sed 'N;s/\n/ \& /'

perl approaches.

perl -pe '$_="$. & $_"' filename
perl -pe 's/^/$. & /' filename
  • How did you find this syntax sed = filename | ...? - - I did not know that you can use sed with equal symbol. - - Can your sed statement work in dynamic environments? Any weaknesses? – Léo Léopold Hertz 준영 Dec 28 '16 at 20:32
  • 1
    @LéoLéopoldHertz준영 I looked under man page, the = operator is under "Zero- or One- address Commands" section. – Sergiy Kolodyazhnyy Dec 28 '16 at 20:49
  • Yes, = Print the current line number. So the feature is actually built-in in sed. Nice! – Léo Léopold Hertz 준영 Dec 29 '16 at 7:30
3

Python can be a good alternative tool for this:

$ python -c "import sys;lines=[str(i)+' & '+l for i,l in enumerate(sys.stdin,1)]; print ''.join(lines)" < input.txt      
1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

The way this works is that we redirect text into python's stdin, and read lines from there. enumerate() function is what gives line count, with sys.stdin specified as input and 1 is the starting index. The rest is simple - we make up list of new strings by casting index as string joined together with ' & ' string, and the line itself. Finally, all that is reassembled from list into one test by the ''.join() function.

Alternatively , here's a multi-line version for a script file or simply for readability:

#!/usr/bin/env python
import sys

for index,line in enumerate(sys.stdin,1):
    print str(index) + ' & ' + line.strip()

Works just the same:

$ ./line_counter.py  < input.txt                                                                                         
1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

But if you prefer doing it in bash, then that can be done as well:

$ counter=1; while read line ; do printf "%s & %s\n" "$counter" "$line" ; counter=$(($counter+1)) ; done < input.txt
1 & What & South Dragon & North Dragon    & 5 \ hline
2 & What & South Dragon & North Dragon    & 5 \ hline
3 & What & South Dragon & North Dragon    & 5 \ hline
  • 1
    @LéoLéopoldHertz준영 Well, if I were to do that without enumerate, I would need a variable that tracks number of lines, and I need to initiate that variable, and increment each time. Using enumerate() saves up like 3 lines of code. It is useful when dealing with other things, like processing items in lists. See docs.python.org/2/library/functions.html#enumerate – Sergiy Kolodyazhnyy Dec 28 '16 at 20:39
  • @LéoLéopoldHertz준영 if you understand using counter like I do in bash example, then feel free to use that :) I just found from experience enumerate() to be more elegant, but that's just my opinion. By all means, use other method if you think it's more clear – Sergiy Kolodyazhnyy Dec 28 '16 at 20:42
  • OK, enumerate is clearer than variable instantiation. Can lambda expression save some space? – Léo Léopold Hertz 준영 Dec 29 '16 at 7:32
  • @LéoLéopoldHertz준영 It could save space in a long script, but in this case, i just don't see how that could help. – Sergiy Kolodyazhnyy Dec 29 '16 at 8:29
2

This is also an option using cat -n with auto numbering:

while read num line;do echo $num "&" $line;done <<<$(cat -n a.txt)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.