我有一个包含表示文件类型的字符串的输入流。我想打印所有非文本文件类型或者是 PostScript(PostScript 是一种文本文件类型)。我尝试了以下 sed 表达式:
sed -n '/PostScript/pb; /text/!p'
但是,这会返回一个错误:
sed: -e expression #1, char 14: extra characters after command
bp
这让我感到困惑,因为我认为在模式之后指定多个命令(例如)是可以接受的。
我可以使用以下表达式获得我想要的行为:
sed -n '/PostScript/p; /PostScript/b; /text/!p'
如何在不重复/PostScript/
表达式中的模式的情况下获得我想要的行为?
答案1
让一组命令一起执行(例如,受模式匹配之类的条件影响)的常见方法是用花括号将它们分组。
使用 GNU sed
:
sed -n '/PostScript/{p; b}; /text/!p'
在这两种情况下都没有分组并且有任何sed
分支到脚本末尾,并删除其他行:
sed -e '/PostScript/b' -e '/text/!b' -e 'd'
另外,为了记录:
bp
我认为在模式之后指定多个命令(例如)是可以接受的。
地址的编辑命令(您所说的模式是上下文地址)是一回事,而s
ubstitution 标志g
、p
、w
和no.
是另一回事。
后者的语法是
s/pattern/replacement/[flags]
换句话说,标志可以组合(例如gp
或7w outfile
),而前者的语法是
[2addr] {editing command
editing command
...
}
换句话说,命令必须用换行符分隔(在某些情况下它们可以用分号分隔)。
答案2
POSIXly:
$ sed -n '/PostScript/p; //b
/text/!p'
POSIX 定义如果正则表达式为空,sed
则其行为应如同应用最后一个命令中使用的最后一个 RE。
使用您的命令,您需要;
Betweenp
和b
才能使其与 GNU sed 一起使用:
$ sed -n '/PostScript/p; //b; /text/!p'
对于 POSIX sed,您不能使用,//b;
因为;
是有效的分支名称。您需要使用换行符作为命令之间的终止符。