Jamie Johnson
Jamie Johnson

Reputation: 61

How can I get a range of line every nth interval using awk, sed, or other unix command?

I know how to get a range of lines by using awk and sed. I also do know how to print out every nth line using awk and sed.

However, I don't know how to combined the two.

For example, I have a file with 1780000 lines.

For every 17800th line, I would like to print 17800th line plus the two after that.

So if I have a file with 1780000 lines and it starts from 1 and ends at 1780000, this will print:

1
2
3
17800
17801
17802
35600
35601
35602
# ... and so on.

Does anyone know how to get a range of line every nth interval using awk, sed, or other unix command?

Upvotes: 6

Views: 5552

Answers (4)

RARE Kpop Manifesto
RARE Kpop Manifesto

Reputation: 2865

awk solution that skips ALL division/modulo/per-row-counter ops, and updates the tracker's value only once every N rows :

jot 80000 | 

mawk 'NR == (_? _ : (__ = ___ + !+_)^(_ = "+" (+_))),
      NR == __  &&   __ = ___ + (_ += ____)' ___=2 ____=17800 

1
2
3
17800
17801
17802
35600
35601
35602
53400
53401
53402
71200
71201
71202

Upvotes: 0

Weihang Jian
Weihang Jian

Reputation: 8755

seq -f %.0f 1780000 | awk 'NR < 4 || NR % 17800 < 3' | head

output:

1
2
3
17800
17801
17802
35600
35601
35602
53400

Explanation

  1. The NR < 4 is for the first 3 lines because the requirement For every 17800th line, print 17800th line plus the two after that. doesn't fit the output you gave.
  2. Here I use head for reducing the output size and you should remove it in your use case.
  3. For GNU seq, you don't need -f %.0f.

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 204164

$ cat file
1
2
3
4
5
6
7
8
9
10

$ awk '!(NR%3)' file
3
6
9

$ awk -v intvl=3 -v delta=2 '!(NR%intvl){print "-----"; c=delta} c&&c--' file
-----
3
4
-----
6
7
-----
9
10

$ awk -v intvl=4 -v delta=2 '!(NR%intvl){print "-----"; c=delta} c&&c--' file
-----
4
5
-----
8
9

$ awk -v intvl=4 -v delta=3 '!(NR%intvl){print "-----"; c=delta} c&&c--' file
-----
4
5
6
-----
8
9
10

Upvotes: 2

perreal
perreal

Reputation: 98088

Using GNU sed:

sed -n '0~17800{N;N;p}' input

Meaning,

For every 17800th line: 0~17800
  Read two lines: {N;N;
  And print these out: p}

We can also add the first three lines:

sed -n -e '1,3p' -e '0~17800{N;N;p}' input

Using Awk, this would be simpler:

awk 'NR%17800<3 || NR==3 {print}' input

Upvotes: 5

Related Questions