Have sed ignore non-matching lines
How can I make sed
filter matching lines according to some expression, but ignore non-matching lines, instead of letting them print?
As a real example, I want to run scalac
(the Scala compiler) on a set of files, and read from its -verbose
output the .class
files created. scalac -verbose
outputs a bunch of messages, but we're only interested in those of the form [wrote some-class-name.class]
.
What I'm currently doing is this (|&
is bash 4.0's way to pipe stderr to the next program):
$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'
This will extract the file names from the messages we're interested in, but will also let all other messages pass through unchanged! Of course we开发者_StackOverflow社区 could do instead this:
$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
sed 's/^\[wrote \(.*\.class\)\]$/\1/'
which works but looks very much like going around the real problem, which is how to instruct sed
to ignore non-matching lines from the input. So how do we do that?
If you don't want to print lines that don't match, you can use the combination of
-n
option which tells sed not to printp
flag which tells sed to print what is matched
This gives:
sed -n 's/.../.../p'
Another way with plain sed:
sed -e 's/.../.../;t;d'
s///
is a substituion, t
without any label conditionally skips all following commands, d
deletes line.
No need for perl or grep.
(edited after Nicholas Riley's suggestion)
Rapsey raised a relevant point about multiple substitutions expressions.
- First, quoting an Unix SE answer, you can "prefix most sed commands with an address to limit the lines to which they apply".
- Second, you can group commands within curly braces
{}
(separated with a semi-colon;
or a new line) - Third, add the print flag p on the last substitution
Syntax:
sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'
Example (see Here document for more details):
Code:
sed -n -e '/^ha/ {s/h/k/g;s/a/e/gp}' <<SAMPLE haha hihi SAMPLE
Result:
keke
sed -n '/.../!p'
There is no need for a substitution.
精彩评论