忽略不匹配的行

如何使 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/'

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

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

它可以工作,但看起来非常像绕过真正的问题,即如何指示 sed忽略来自输入的不匹配行。那我们要怎么做?

57209 次浏览

如果不希望打印不匹配的行,可以使用

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

这意味着:

sed -n 's/.../.../p'

另一种使用简单 sed 的方法:

sed -e 's/.../.../;t;d'

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

不需要 perl 或 grep。

(编辑后尼古拉斯 · 莱利的建议)

sed -n '/.../!p'

没有必要替换。

Rapsey 提出了一个关于多重替换表达式的相关观点。

  • 首先,引用 Unix SE 的答案,您可以“在大多数 sed 命令前面加上一个地址,以限制它们所应用的行数”。
  • 其次,可以在大括号 {}内对命令进行分组(用分号 ;或新行分隔)
  • 第三,在最后一个替换上添加打印标志 P

句法:

sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'

示例(详情请参阅 Here document) :

  • 密码:

    sed -n -e '/^ha/ {s/h/k/g;s/a/e/gp}' <<SAMPLE
    haha
    hihi
    SAMPLE
    
  • 结果:

    keke