我有这个 sed 过滤器:
/.*[1-9][0-9][0-9] .*/{
s/.*\([1-9][0-9][0-9] .*\)/\1/
}
/.*[1-9][0-9] .*/{
s/.*\([1-9][0-9] .*\)/\1/
}
/.*[0-9] .*/{ # but this is always preferred/executed
s/.*\([0-9] .*\)/\1/
}
问题是前两个限制性更强,并且它们没有被执行,因为最后第三个更“强大”,因为它包括前两个。有没有办法让 sed 采取前两个,并带有“优先顺序”?喜欢
if the first matches
do first things
elif the second matches
do second things
elif the third matches
do third things
答案1
在不知道这些正则表达式的目标是什么并且没有测试数据的情况下,您需要的是一个t
分支,它将导致您sed
分支到脚本的末尾,并在成功完成替换后跳过处理其余代码。
sed '/regexp1/ s/do/things/; t
/regexp2/ s/do/things/; t
/regexp3/ s/do/things/ ' infile
根据您使用的命令,您还可以使用b
分支(无条件分支到指定的标签,或者如果省略标签则分支到脚本的末尾)sed -e '/regex/{ s/do/things/; b' -e '}; ...'
。
来自“man sed”:
t label
如果自上次读取输入行以来以及自上次 t 或 T 命令以来 as/// 已成功替换,则分支到 label;如果省略标签,则分支到脚本末尾。b label
分支到标签;如果省略标签,则分支到脚本末尾。
答案2
你误解了正在发生的事情。 Sed 始终执行所有按顺序匹配的模式。问题在于最后一个模式正在重新编辑第一个模式的内容。
另外,如果 s/// 上的搜索模式与匹配模式相同,那么它就是多余的,并且您实际上并没有在这些模式之间进行不同的更改,那么您如何知道它运行的是哪一个呢?