-2

I want to extract specific lines (say lines 2, and 4 through 6) from a file and redirect them to a file in the command line / pipe it to another program.

Which tool would do the job the fastest / cleanest (sed, awk, perl, shell)?

fedorqui
  • 275,237
  • 103
  • 548
  • 598
jh314
  • 27,144
  • 16
  • 62
  • 82
  • 2
    Why is Perl a bad tag? And how can I improve this question? Thanks! – jh314 Jun 24 '13 at 15:39
  • 1
    I'm a little shocked that this isn't a dupe – it's essentially a classic question. But I don't think it's a *bad* question. – kojiro Jun 24 '13 at 15:55
  • possible duplicate of [unix command to read line from a file by passing line number](http://stackoverflow.com/questions/3286084/unix-command-to-read-line-from-a-file-by-passing-line-number) – l0b0 Jun 24 '13 at 16:01
  • 1
    Not completely a dupe, though, since this question asks how to get one line, then, later, a range. – kojiro Jun 24 '13 at 18:15
  • Now that I think about it, this question as phrased comes across as shopping (because it implies you already know which tools are available and just want to know which *is best*). It might be better to simply ask how to pick arbitrary lines (both individual lines and ranges) out of a file and not assume anything about the toolchain. The part about cleanliness and speed should go without saying. – kojiro Jun 25 '13 at 12:46

5 Answers5

6

Sed has a nice way of doing this:

sed -ne '2p' -e '4,6p'

for example:

$ printf '%s\n' {1..100} | sed -ne '2p' -e '4,6p'
2
4
5
6
kojiro
  • 74,557
  • 19
  • 143
  • 201
4

Use awk and its parameter NR. You can compose conditional expressions such as:

$ cat a
aa
bb
cc
dd
ee
$ awk 'NR==3' a #print line number 3
cc
$ awk 'NR==3, NR==5' a #print from line number 3 up to number 5
cc
dd
ee
$ awk 'NR>2 && NR<7' a #print lines whose number is in the range (2,7)
cc
dd
ee

etc.

In your case,

$ awk 'NR==2; NR>=4 && NR<=6' a #print line number 2 and from 4 to 6
fedorqui
  • 275,237
  • 103
  • 548
  • 598
4
awk 'NR==2 || NR>=4 && NR<=6'

or

awk 'NR==2; NR==4,NR==6'
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
1

You can do it using just head and tail ...

For example:

NR=3; cat test.txt | head -n $NR | tail -n -1

extracts line 3 from test.txt; and

NB=2; NR=3; cat test.txt | head -n $(expr $NR \+ $NB) | tail -n -$NB

extracts line 3 to 5.

Ben
  • 7,372
  • 8
  • 38
  • 46
1

Use awk and keep it clear and simple:

awk 'NR==2 || (NR>=4 && NR<=6)' file
Ed Morton
  • 188,023
  • 17
  • 78
  • 185