如何使用 POSIX 扩展正则表达式(对于 sed)匹配除字符串之外的任何字符?

如何使用 POSIX 扩展正则表达式(对于 sed)匹配除字符串之外的任何字符?

我正在处理一个字符串:

Input File
----
some**wor*ds**with**asterisks

通过告诉sed匹配任何字符不是星号:

echo "some**words** **" | sed -E 's/\*\*([^*]+)\*\*/FOO\1FOO/g'

这将正确输出:someFOOwordsFOO **

但这不适用于上述情况Input File。因此,我想告诉 sed 忽略随后的两个星号。

sed -E 's/\*\*([^*]+)\*\*/FOO\1FOO}/g' IF

会输出:

some**wor*dsFOOwithFOOasterisks

我应该喜欢的是:

someFOOwor*dsFOOwith**asterisks

答案1

使用 Perl 非贪婪地捕获单词:

$ echo 'some**wor*ds**with**asterisks' | perl -pe 's/\*\*(.*?)\*\*/FOO$1FOO/'
someFOOwor*dsFOOwith**asterisks

这从第一个**到下一个最接近的匹配**,并将匹配位替换为FOO,两者之间的子字符串**,然后FOO再次。如果没有非贪婪匹配,**表达式中的第二个将匹配最后的这样的字符串就行了,之后with

使用sed

$ echo 'some**wor*ds**with**asterisks' | sed '/\*\*.*\*\*/ { s/\*\*/FOO/; s//FOO/; }'
someFOOwor*dsFOOwith**asterisks

**这会将行中的第一个替换为FOO,然后也替换为下一个,但前提是该行包含**后跟另一个**.

请注意,我们不关心这两者**位于行的哪个子字符串,只关心 a**与下一个最接近的 匹配**。这适用于上面的两个命令。


看一下评论中的例子:

some**wor*ds**with**asterisks some**wor*ds**with**asterisks

这可以通过显式循环来处理,sed迭代已经给定的解决方案,直到没有更多的事情可做:

sed -e ':again' -e '/\*\*.*\*\*/ { s/\*\*/FOO/; s//FOO/; b again; }'

g只需将标志添加到替换中,即可使 Perl 变体处理模式的重复实例:

perl -pe 's/\*\*(.*?)\*\*/FOO$1FOO/g'

相关内容