Show all lines before a match

5,363

Solution 1

  • 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

Solution 2

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

sed '0,/foo/!d' file

Solution 3

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

Solution 4

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

Solution 5

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.

Share:
5,363

Related videos on Youtube

Mario Palumbo
Author by

Mario Palumbo

Updated on September 18, 2022

Comments

  • Mario Palumbo
    Mario Palumbo over 1 year

    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.

  • steeldriver
    steeldriver over 3 years
    With GNU sed, there's also Q to quit without default-printing the matched line
  • Mario Palumbo
    Mario Palumbo over 3 years
    What is tac? Perhaps cat?
  • schrodingerscatcuriosity
    schrodingerscatcuriosity over 3 years
    tac is a reverse cat ;)
  • Mario Palumbo
    Mario Palumbo over 3 years
    there is the perl alternative? Is more kind.
  • steeldriver
    steeldriver over 3 years
    @MarioPalumbo perl -pe 'exit if /foo/'; similarly awk '/foo/{exit} 1'
  • Mario Palumbo
    Mario Palumbo over 3 years
    @steeldriver you are genius. Your reply is the V green reply. Comment this as answer
  • Peter Cordes
    Peter Cordes over 3 years
    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.
  • llywrch
    llywrch over 3 years
    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.
  • Mario Palumbo
    Mario Palumbo over 3 years
    Can i have an example of OS with no-GNU sed?
  • Mario Palumbo
    Mario Palumbo over 3 years
    It would be great if they introduced this feature to Ubuntu/Debian as well.
  • Quasímodo
    Quasímodo over 3 years
    @MarioPalumbo OSes are not bound to a specific version of Sed. BSD and Mac by default don't use GNU Sed. Also minimal systems (e.g. Busybox) don't feature GNU Sed. Since it has many extensions, it is larger.
  • user.dz
    user.dz over 3 years
    @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.