Is there a very simple way (maybe using one line with sed?) to get n lines, starting at ath line within this chunk of n lines, for every m lines?

More specifically, I have a file with millions of lines. For every 4 lines, I want to get the first two lines.

But I guess I also want to get an idea of doing this in other similar situations. That's why I asked a more general question here.

  • 4
    Please edit question for clarity. – mkc Feb 12 '17 at 16:21
  • 1
    Do you mean sed '1~3,+1 ! d' file_with_million_lines ? – Costas Feb 12 '17 at 16:34
  • You might want to consider Awk as well - GNU sed has a nice addressing mode for this, but it's not portable. – Toby Speight Feb 13 '17 at 11:06

With gnu split:

split -l ${m} --filter="head -n ${n}" infile

and if you wanted to do it only after the ith line, just redirect the previous lines to /dev/null:

{ head -n ${i} >/dev/null; split -l ${m} --filter="head -n ${n}"; } <infile

If you don't have access to gnu tools you could use awk:

awk -vn=2 -vm=4 -vi=7 'NR<=i{next}; (NR-i)%m==1{c=1}; c++<=n' infile
  • This solved the more general problem for me. Thank you. – coffee Feb 12 '17 at 16:37
  • 2
    Simpler awk: 'NR<=i{next} c++%m<n' – dave_thompson_085 Feb 13 '17 at 13:26

You can use the ~ in the address in GNU sed:

sed -n '1~4p;2~4p'

Which reads "Print the first line every 4 lines, and print the second line every 4 lines" or "Starting from line 1, print every 4th line, and starting from line 2, print every 4th line".


For GNU sed

sed '3~4,+1 d' file

or more general:

sed "$((m-n+1))~$m,+$((m-n-1)) d" file

Or this, gnu sed:

sed -n -e '1~4 {N; p;}' file

-n surpresses the output. If at line 1+4*k (k=iterator) the current line and the next line is read into pattern space and p prints the (current) pattern space (i.e. temporally enabling the output)

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.