0

I have a simple question. I have a file containing:

more random text

*foo*
there
is 
random
text
here
*foo*

foo
even
more
random
text
here
foo
more random text

(to clarify between which parts i want the result from, i added the *'s next to foo. The *'s are not in the file.)

I only want to print out the multiple lines between the first 2 instances of foo.

I tried searching for ways to let "foo" occur only once and then remove it. But i didnt get that far. However i did find the way to remove all the "more random text" using: sed '/foo/,/foo/p' but i couldnt find a way using sed, or awk to only match ones and print the output.

Can anyone help me out?

3 Answers3

1

With sed:

$ sed -n '/foo/{:a;n;/foo/q;p;ba}' infile
there
is
random
text
here

Explained:

/foo/ {     # If we match "foo"
    :a      # Label to branch to
    n       # Discard current line, read next line (does not print because of -n)
    /foo/q  # If we match the closing "foo", then quit
    p       # Print line (is a line between two "foo"s)
    ba      # Branch to :a
}

Some seds complain about braces in one-liners; in those cases, this should work:

sed -n '/foo/ {
    :a
    n
    /foo/q
    p
    ba
}' infile
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
  • Thank you for your contribution to my question. Love sed and awk both. Not an expert on them, but im glad i and others can choose. –  Jan 28 '16 at 10:12
0
$ awk '/foo/{++c;next} c==1' file
there
is
random
text
here

$ awk '/foo/{++c;next} c==3' file
even
more
random
text
here

or with GNU awk for multi-char RS you COULD do:

$ awk -v RS='(^|\n)[^\n]*foo[^\n]*(\n|$)' 'NR==2' file
there
is
random
text
here

$ awk -v RS='(^|\n)[^\n]*foo[^\n]*(\n|$)' 'NR==4' file
even
more
random
text
here

See https://stackoverflow.com/a/17914105/1745001 for other ways of printing after a condition is true.

Community
  • 1
  • 1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • please explain the logic behind the same – Sadhun Jan 25 '16 at 10:46
  • What do you THINK it means? I'll be happy to answer specific questions but it'd be kinda like explaining a Hello World program so idk where you need help with it. – Ed Morton Jan 25 '16 at 14:44
0

Since checking for "foo" (using /foo/) is relatively expensive, the following avoids that check and will work with all awks worthy of the name:

awk 'c==2 {next} /foo/{++c;next} c==1' file
peak
  • 105,803
  • 17
  • 152
  • 177