有sed忽略不匹配的行

Pag*_*gas 82 sed

如何sed根据某个表达式创建过滤器匹配行,但忽略不匹配的行,而不是让它们打印?

作为一个真实的例子,我想scalac在一组文件上运行(Scala编译器),并从其-verbose输出中读取.class创建的文件.scalac -verbose输出一堆消息,但我们只对表单中的消息感兴趣[wrote some-class-name.class].我目前正在做的是这个(|&是bash 4.0将stderr传递给下一个程序的方法):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'
Run Code Online (Sandbox Code Playgroud)

这将从我们感兴趣的消息中提取文件名,但也会让所有其他消息保持不变!当然我们可以这样做:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
  sed 's/^\[wrote \(.*\.class\)\]$/\1/'
Run Code Online (Sandbox Code Playgroud)

哪个有效,但看起来非常像绕过真正的问题,这是如何指示sed从输入中忽略不匹配的行.那我们该怎么做呢?

mou*_*iel 226

如果您不想打印不匹配的行,可以使用组合

  • -n 告诉sed不要打印的选项
  • p 告诉sed打印匹配的标志

这给出了:

sed -n 's/.../.../p'
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的一个缺点是,如果您有多个匹配的表达式,结果也将被多次打印.例如:`echo foo | sed -n -e's/foo/bar/p'-e's/bar/oof/p'`将在单独的行上输出"bar"和"oof".虽然goto-label变种无法处理多个模式,因为如果第一个模式不匹配,它将删除该行. (2认同)

lio*_*ori 80

普通sed的另一种方式:

sed -e 's/.../.../;t;d'
Run Code Online (Sandbox Code Playgroud)

s///是一个替代品,t没有任何标签有条件地跳过所有以下命令,d删除行.

不需要perl或grep.

(根据Nicholas Riley的建议编辑)

  • 更好的是:`sed -e's /.../.../'-e'tx'-e'd'-e':x'`(在对[类似问题]的评论中建议(http: //stackoverflow.com/a/1252191/312785)). (5认同)
  • 在OS X 10.8.2上,我必须用换行符而不是分号来分隔`tx`和`d`,因为我得到了'undefined label'x; d;:x'`. (3认同)