views:

579

answers:

7

Say I've got a bunch of files that are all >100 lines long. I'd like to trim off the top 14 lines and the bottom 9 lines, leaving only the lines in the middle. This command will trim off the top fourteen:

cat myfile.txt | tail -n +15

Is there another command I can pipe through to trim off the bottom 9 without explicitly passing the length of the file?

Edited to add: My version of head (Mac OS 10.5) doesn't accept a negative number of lines as a parameter.

A: 

The head command should do what you want. It woks just like tail but from the other end of the file.

jbourque
head appears to only let me display the first N lines, which is different from trimming the last N lines. (I don't know exactly how many lines I need to see, just that I need to get rid of the last 9.)
Christopher Ashworth
head outputs some lines from the beginning - with positive argument, it returns n lines, with negative argument, it returns all but (first) n lines. Tail is similar.
jpalecek
+4  A: 

You could use sed:

sed -n -e :a -e '1,9!{P;N;D;};N;ba' myfile.txt

You can also use sed for the first 15:

sed '1,15d' myfile.txt
Rob Hruska
+6  A: 

Use a negative number of lines with the head command:

cat myfile.txt | head -n  -9

That prints everything except the last 9 lines.

yjerem
+3  A: 

What jbourque said is completely right. He just wasn't too wordy about it:

cat myfile.txt | tail -n +15 | head -n -9
Johannes Schaub - litb
Much as I hate upvoting those with a higher rep :-), this is exactly what I would have said if I'd turned the computer on 5 minutes earlier this morning. +1.
paxdiablo
thanks pax. very appreciated :)
Johannes Schaub - litb
+1  A: 

If you can recognize the last 9 lines by a distinctive pattern for the first of those lines, then a simple sed command would do the trick:

sed -e '1,15d' -e '/distinctive-pattern/,$d' $file

If you need a pure numeric offset from the bottom, standard (as opposed to GNU) sed won't help, but ed would:

ed $file <<'!'
1,15d
$-8,$d
w
q
!

This overwrites the original files. You'd have to script where the file is written to if you wanted to avoid that.

Jonathan Leffler
+5  A: 

This will work on OS X and might be a bit more easily understandable than the sed example:

< myfile.txt tail -n +15 | tail -r | tail -n +10 | tail -r

Of course, if you can get your hands on GNU's version of head, it can be done even more elegantly:

< myfile.txt tail -n +15 | head -n -9

Be aware the tail starts at the nth line while head skips n lines of the input.

hop
A: 

This should also work, and does things in a single process:

seq 15 | 
awk -v N=5 '
  { lines[NR % N] = $0 } 
  END { i = NR-N+1; if (i<0) i=0; for (; i <= NR; ++i) print lines[i % N] }'

(The seq is just an easy way to produce some test data.)

Lars Wirzenius