suszterpatt
suszterpatt

Reputation: 8273

How can I filter a line pattern with sed?

Suppose I have a shell script, foo.sh, that produces repeating sets of data like this:

<name 1>
<address 1>
<mother's name 1>
<pet's name 1>
<comment 1>
<name 2>
<address 2>
<mother's name 2>
<pet's name 2>
<comment 2>
...

I want to extract the 1st and 3rd lines from each 5-line block, so the modified output looks like this:

<name 1>
<mother's name 1>
<name 2>
<mother's name 2>
...

The catch being that there's no pattern unique to these lines, so I need to filter by line numbers specifically. How can this be done?

Upvotes: 1

Views: 3005

Answers (4)

Tomasz Elendt
Tomasz Elendt

Reputation: 1475

Using GNU sed:

sed -n '1~5p;3~5p' file.txt

From GNU sed manual:

first~step
    Match every step'th line starting with line first. For example, ``sed -n 1~2p''
    will print all the odd-numbered lines in the input stream, and the address 2~5
    will match every fifth line, starting with the second. first can be zero; in
    this case, sed operates as if it were equal to step.  (This is an extension.)

Upvotes: 4

potong
potong

Reputation: 58371

This might work for you:

sed -n 'h;n;n;H;n;n;g;p' file

Upvotes: 0

jcuenod
jcuenod

Reputation: 58375

Can you use awk?

awk 'NR % 5 == 1 || NR % 5 == 3' foofile

So basically what's happening is

  • awk opens foofile.
  • it reads through it line by line
  • the line number is divided by five and if the remainder is 1 or 3 (i.e. the first or the third line in a block of 5) then it prints that line

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363507

I'm not a sed expert, but you can do this in Awk:

$ awk '(i==0 || i==2) { print }
                      { i = (i+1) % 5 }
  ' < filename.txt

Or, in one line

$ awk '(NR%5==1 || NR%5==3)' < filename.txt

Upvotes: 3

Related Questions