PonyEars
PonyEars

Reputation: 2254

how can I get sed to quit after the first matching address range?

I have a file:

header
trigger
text1
text2
trigger
text5
trigger
...
trigger
...

I want sed to only match between the first two occurrences of 'trigger'. So I tried:

sed -n '/trigger/,/trigger/p'

But as the man page for sed says, that matches all occurrences within two lines with 'trigger'. I want sed to quit after the first match, so the output would be:

trigger
text1
text2
trigger

How do I accomplish this?

Upvotes: 37

Views: 29055

Answers (3)

janos
janos

Reputation: 124714

You can do this with a loop in GNU sed:

sed -n '/trigger/{p; :loop n; p; /trigger/q; b loop}'

Explanation:

  1. When you see the first /trigger/, start a block of commands
  2. p -- print the line
  3. :loop -- set a label named loop
  4. n -- get the next line
  5. p -- print the line
  6. /trigger/q -- if the line matches /trigger/ then exit sed
  7. b -- jump to loop

Upvotes: 48

Jotne
Jotne

Reputation: 41460

Another awk variation:

awk '/trigger/{f++} f; f>1 {exit}' file
  • /trigger/{f++} if word trigger is found increment f by 1 (it will be 1 for first time seen and 2 for second time etc)
  • f; test if f is true, if so, do the default action, print the line.
  • f>1 {exit} if f is larger then 1 (it will be 2 at the second hit) exit the program.

Upvotes: 5

jkshah
jkshah

Reputation: 11713

While jason's ans is what you're looking for, I would have preferred using awk for this task

awk '/trigger/{p++} p==2{print; exit} p>=1' file

Output:

trigger
text1
text2
trigger

This would provide more flexibility to chose lines between nth and mthe occurrence of trigger.

E.g.

$ awk -v n=2 -v m=3 '/trigger/{p++} p==m{print; exit} p>=n' file
trigger
text5
trigger

Upvotes: 11

Related Questions