11

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
    Please don't put answers in the question. You can add an answer with the Perl solution instead. – Quasímodo Oct 20 at 11:50
  • When I have published a reply in this topic: https://askubuntu.com/questions/1277701 i have received this comment: Edit your Q instead. – bac0n Sep 25 at 13:02 Make up your minds on what is best to do. – Mario Palumbo Oct 22 at 20:34
12
  • 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
    
| improve this answer | |
  • 3
    With GNU sed, there's also Q to quit without default-printing the matched line – steeldriver Oct 18 at 12:51
  • there is the perl alternative? Is more kind. – Mario Palumbo Oct 18 at 14:52
  • 2
    @MarioPalumbo perl -pe 'exit if /foo/'; similarly awk '/foo/{exit} 1' – steeldriver Oct 18 at 15:04
  • 1
    @steeldriver you are genius. Your reply is the V green reply. Comment this as answer – Mario Palumbo Oct 18 at 15:07
  • Can i have an example of OS with no-GNU sed? – Mario Palumbo Oct 22 at 20:18
6

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

sed '0,/foo/!d' file
| improve this answer | |
5

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
| improve this answer | |
  • What is tac? Perhaps cat? – Mario Palumbo Oct 18 at 14:36
  • 4
    tac is a reverse cat ;) – schrodigerscatcuriosity Oct 18 at 14:37
  • 1
    Wow. I've been using UNIX off-&-on (mostly on) for almost 30 years, & never heard of "tac" before today. There's always something new to learn. – llywrch Oct 19 at 15:36
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
| improve this answer | |
  • 1
    For huge files (a large fraction of your total RAM), if you aren't sure a match exists you might just grep -q input.txt && sed '/pattern/q input.txt to verify a match before running sed. Or get the line number from grep and use it for head. Slower than 1-pass when a match does exist, unless it means you avoided swap thrashing. Also doesn't work as a filter; needs to reopen its input from the start. – Peter Cordes Oct 19 at 7:33
2

To print all lines before the match,

perl -pe 'exit if /foo/' file
awk '/foo/{exit} 1' file
| improve this answer | |
2

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.

| improve this answer | |
  • It would be great if they introduced this feature to Ubuntu/Debian as well. – Mario Palumbo Oct 22 at 20:58
  • @MarioPalumbo , That would be great. I even hope to the hole tool copied both side as extra gnu_* tools on BSD and bsd_* tools on GNU. But it seems hard due to old history of licensing. – user.dz Oct 23 at 7:01
1

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"
| improve this answer | |

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.