4

I am trying to retrieve 2 lines of text with sed, every 10 lines (10, 11, 20, 21, 30, 31, ...).

For lines 10 and 11 I could use sed -n '10,11p' file or sed -n '10,+1p' file. And for the range (lines 10, 20, 30, ...) sed -n '10,~10p' file. But is it possible to combine somehow both things?

sed -n '10,~10,+1p' file is not working.

I assume this is a duplicate, but I can't find any reference. Thanks!

10

Use the ADDR1,ADDR2 with FIRST~STEP as ADDR1 and +OFFSET as ADDR2, so:

$ seq 30 | sed '10~10,+1!d'
10
11
20
21
30

In anycase, note that both ~ and + are non-standard GNU extensions.

See info sed 'line selection' and info sed 'range of lines' on a GNU system for details.

POSIXly, you'd use:

seq 30 | sed -n '1n;n;n;n;n;n;n;n;n;p;n;p'
| improve this answer | |
  • beautiful! thanks. I just understood how I misused ~ – manolius Oct 30 at 12:00
7

How about an awk solution?

awk '(FNR>1) && (FNR%10<2)' file
  • FNR is awks automatically updated per-file line-counter
  • Any condition outside of a "rule block" ({ ... }) that evaluates to "true" (and be it the string 1) will instruct awk to print the current line, including all modifications made so far.
  • So, (FNR>1) && (FNR%10<2) will print the current line, if it is not the first line, and if the line number is an integer multiple of 10 (or +1 from such a multiple at most). This is equivalent to "every 10th and line and the following".
| improve this answer | |
  • I assumed awk was an option, but I am not able to learn it. I end up wasting so much time every time. Thanks! – manolius Oct 30 at 12:01
  • @manolius I know, awk has quite a learning curve. For me it turned out worthwile, but it depends a lot on what your tasks look like. – AdminBee Oct 30 at 12:03
  • @manolius I have added some in-depth explanation; perhaps it can serve as starting point for learning awk ... ;) – AdminBee Oct 30 at 12:27
  • You could also make use of getline ex. awk '!(FNR%10){print; if(getline > 0) print}' - which perhaps makes the intent clearer – steeldriver Oct 30 at 15:03
  • 1
    @steeldriver Nice suggestion, but for users not acquainted should probably step back from getline. – Quasímodo Oct 30 at 15:37
3

Using awk we can do as shewn. NR is line number in awk parlance.

$ awk 'NR ~ /.[10]$/'  file

With sed we could do as shown below where we increment the hold space till we hit the 10 count of newlines.

$ sed -nE 'x
  /\n{9}/{
    z;x;$d
    N;p;D
  }
  s/$/\n/;h
' file
$ perl -ne '$.%10||print($_.<>)' file
| improve this answer | |

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.