Show all lines before a match
Solution 1
-
Including the match,
sed '/foo/q' file
It is better to quit
sed
as soon as a match is found, otherwisesed
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 thep
command will be printed. Since thefoo
line triggers theq
uit action, it does not reachp
and thus is not printed.-
If your
sed
is GNU's, this can be simplified tosed '/foo/Q' file
-
References
-
/foo/
— Addresses -
q
,p
— Often-used commands -
Q
— GNU Sed extended commands -
-n
— Command-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 line1!H
-- append pattern space to hold space when not on the first line/foo/{...}
-- on matching/foo/
,g
-- copy hold space to pattern spacep
-- print pattern spaceq
-- 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.
Related videos on Youtube
Mario Palumbo
Updated on September 18, 2022Comments
-
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 over 3 yearsWith GNU sed, there's also
Q
to quit without default-printing the matched line -
Mario Palumbo over 3 yearsWhat is
tac
? Perhapscat
? -
schrodingerscatcuriosity over 3 years
tac
is a reversecat
;) -
Mario Palumbo over 3 yearsthere is the
perl
alternative? Is more kind. -
steeldriver over 3 years@MarioPalumbo
perl -pe 'exit if /foo/'
; similarlyawk '/foo/{exit} 1'
-
Mario Palumbo over 3 years@steeldriver you are genius. Your reply is the V green reply. Comment this as answer
-
Peter Cordes over 3 yearsFor 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 runningsed
. Or get the line number fromgrep
and use it forhead
. 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 over 3 yearsWow. 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 over 3 yearsCan i have an example of OS with no-GNU sed?
-
Mario Palumbo over 3 yearsIt would be great if they introduced this feature to Ubuntu/Debian as well.
-
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 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.