34

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?

PonyEars
  • 2,144
  • 4
  • 25
  • 30
  • possible duplicate of [How to use sed to return something from first line which matches and quit early?](http://stackoverflow.com/questions/1773939/how-to-use-sed-to-return-something-from-first-line-which-matches-and-quit-early) – SamB Jan 06 '14 at 04:35
  • 1
    Not from what I can see. I want to quit after the first address range, not after the first occurrence. – PonyEars Jan 06 '14 at 04:44

3 Answers3

46

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
janos
  • 120,954
  • 29
  • 226
  • 236
9

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
jkshah
  • 11,387
  • 6
  • 35
  • 45
  • 1
    Thanks. In this particular case, I'm actually needing sed because of a bunch of other commands I haven't shown in the question, but I'd definitely find your awk based solution in the general case. And definitely so for flexibility of the n/mth occurence. Thanks again! – PonyEars Jan 06 '14 at 07:45
5

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.
Jotne
  • 40,548
  • 12
  • 51
  • 55