开发者

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 print
  • p 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜