让sed忽略不匹配的行

让sed忽略不匹配的行,sed,Sed,如何使sed根据某个表达式过滤匹配行,而忽略不匹配行,而不让它们打印 作为一个真实的例子,我想在一组文件上运行scalac(Scala编译器),并从其-verbose输出创建的.class文件scalac-verbose输出一系列消息,但我们只对[编写了一些类名.class]形式的消息感兴趣。 我目前正在做的是(|&是bash4.0将stderr传输到下一个程序的方法): 这将从我们感兴趣的消息中提取文件名,但也将允许所有其他消息不加更改地通过!当然,我们可以这样做: $ scalac -ver

如何使
sed
根据某个表达式过滤匹配行,而忽略不匹配行,而不让它们打印

作为一个真实的例子,我想在一组文件上运行
scalac
(Scala编译器),并从其
-verbose
输出创建的
.class
文件
scalac-verbose
输出一系列消息,但我们只对
[编写了一些类名.class]
形式的消息感兴趣。 我目前正在做的是(
|&
是bash4.0将stderr传输到下一个程序的方法):

这将从我们感兴趣的消息中提取文件名,但也将允许所有其他消息不加更改地通过!当然,我们可以这样做:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
  sed 's/^\[wrote \(.*\.class\)\]$/\1/'
这是可行的,但看起来很像真正的问题,即如何指示
sed
忽略输入中不匹配的行。那么我们如何做到这一点呢?

使用Perl:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/'

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

  • -n
    告诉sed不要打印的选项
  • p
    指示sed打印匹配内容的标志
这使得:

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

普通sed的另一种方式:

sed -e 's/.../.../;t;d'
s//
是一个替换,
t
不带任何标签,有条件地跳过以下所有命令,
d
删除行

不需要perl或grep

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


不需要替换。

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

  • 首先,您可以“在大多数sed命令前面加上地址,以限制它们应用的行”
  • 其次,您可以在大括号中对命令进行分组(用分号分隔;或新行)
  • 第三,在最后一次替换中添加打印标志p
语法:

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

示例(有关更多详细信息,请参阅):

  • 代码:

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

在OS X 10.8.2上,我必须用换行符而不是分号来分隔
tx
d
,因为我得到了
未定义的标签'X;d、 :x'
。更好的是:
sed-e's/../…/'-e'tx'-e'd'-e':x'
(在a的注释中建议)。't'将在没有提供标签的情况下转移到脚本末尾,非常简单:
sed-e's/../'-e't'-e'd'
。人们不知道
-e
选项的含义,所以一般不要提及它。这种方法的一个缺点是,如果有多个匹配的表达式,结果也会被打印多次。例如:
echo foo | sed-n-e's/foo/bar/p'-e's/bar/oof/p'
将在单独的行上同时输出
bar
oof
。尽管goto标签品种也不能处理多个图案,因为如果第一个图案不匹配,它将删除该行。@Rapsey,这是因为您告诉它打印两次。在您告诉它打印两次的单个sed命令中,每个实例都是就地打印的(或者可能是缓冲的)。你要么用管道代替-e,要么只在最后一个-e上加上'p'。这是行不通的,因为最后一个p标志将在最后一个替换表达式所匹配的每一行上起作用。接受的答案应该是mouviciel:或
sed'/…/d'
删除匹配的行
sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'
sed -n -e '/^ha/ {s/h/k/g;s/a/e/gp}' <<SAMPLE
haha
hihi
SAMPLE
keke