我正在处理一个字符串:
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'