Show all lines before a match

I want to show all lines before a match, not only 10, or 7, or 14 for example, as explained in How do I fetch lines before/after the grep result in bash?.

How can I do it? It doesn't matter if the matched line is included or not.

For example, instead of:

... | grep -B 10 -- "foo"

I want:

... | grep -B -- "foo"

But this last code doesn't work.

2

7 Answers

  • Including the match,

    sed '/foo/q' file

    It is better to quit sed as soon as a match is found, otherwise sed would keep reading the file and wasting your time, which would be considerable for large files.

  • Excluding the match,

    sed -n '/foo/q;p' file

    The -n flag means that only lines that reach the p command will be printed. Since the foo line triggers the quit action, it does not reach p and thus is not printed.

    • If your sed is GNU's, this can be simplified to

      sed '/foo/Q' file

References

  1. /foo/Addresses
  2. q, pOften-used commands
  3. QGNU Sed extended commands
  4. -nCommand-line options
6

With GNU sed. Print all lines, from the first to the line with the required string.

sed '0,/foo/!d' file
0

Here's a solution with sed, given the content of file.txt:

bar
baz
moo
foo
loo
zoo

command including pattern

tac file.txt | sed -n '/foo/,$p' | tac

output

bar
baz
moo
foo

excluding pattern

tac file.txt | sed -n -e '/foo/,$p' | tac | sed -n '/foo/!p'
bar
baz
moo
3

Current solutions except schrodigerscatcuriosity's print the file contents even when there's no match. schrodigerscatcuriosity's involves using tac and so requires reading the whole input before looking for matches.

Here's another way to do it with just sed and printing only when there's a match:

sed -n '1h;1!H;/foo/{g;p;q}'
  • 1h -- copy pattern space to hold space when on the first line
  • 1!H -- append pattern space to hold space when not on the first line
  • /foo/{...} -- on matching /foo/,
    • g -- copy hold space to pattern space
    • p -- print pattern space
    • q -- quit
1

To print all lines before the match,

perl -pe 'exit if /foo/' file
awk '/foo/{exit} 1' file

FreeBSD (including MacOS) version does have such feature.

Well -B -1 works, it shows all the lines before the match from the beginning of the file.

... | grep -B -1 -- "foo"

Same for -A -1 , it shows all the lines after the match to the end of the file.

... | grep -A -1 -- "foo"

May be useful for some, It doesn't work with GNU implementation included within Ubuntu.

2

Show ALL lines before a match

You can use large enough number for -B option of grep. For example if your know that input size is no more than 999 you can use it with -B option:

... | grep -B 999 -- "foo"

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like