Linux head/tail with offset

2019-04-03 21:23发布

问题:

Is there a way in Linux to ask for the Head or Tail but with an additional offset of records to ignore.

For example if the file example.lst contains the following:

row01
row02
row03
row04
row05

And I use head -n3 example.lst I can get rows 1 - 3 but what if I want it to skip the first row and get rows 2 - 4?

I ask because some commands have a header which may not be desirable within the search results. For example du -h ~ --max-depth 1 | sort -rh will return the directory size of all folders within the home directory sorted in descending order but will append the current directory to the top of the result set (i.e. ~).

The Head and Tail man pages don't seem to have any offset parameter so maybe there is some kind of range command where the required lines can be specified: e.g. range 2-10 or something?

回答1:

From man tail:

   -n, --lines=K
        output the last K lines, instead of the last 10; 
        or use -n +K to output lines starting with the Kth

You can therefore use ... | tail -n +2 | head -n 3 to get 3 lines starting from line 2.

Non-head/tail methods include sed -n "2,4p" and awk "NR >= 2 && NR <= 4".



回答2:

To get the rows between 2 and 4 (both inclusive), you can use:

head -n4 example.lst | tail -n+2

or

head -n4 example.lst | tail -n3


回答3:

It took make a lot of time to end-up with this solution which, seems to be the only one that covered all usecases (so far):

command | tee full.log | stdbuf -i0 -o0 -e0 awk -v offset=${MAX_LINES:-200} \
          '{
               if (NR <= offset) print;
               else {
                   a[NR] = $0;
                   delete a[NR-offset];
                   printf "." > "/dev/stderr"
                   }
           }
           END {
             print "" > "/dev/stderr";
             for(i=NR-offset+1 > offset ? NR-offset+1: offset+1 ;i<=NR;i++)
             { print a[i]}
           }'

Feature list:

  • live output for head (obviously that for tail is not possible)
  • no use of external files
  • progressbar on stderr, one dot for each line after the MAX_LINES, very useful for long running tasks.
  • avoids possible incorrect logging order due to buffering (stdbuf)