这是使用sed稳健地进行多字符字符串的非贪婪匹配的方法。比方说,你希望每次更改foo...bar
,以<foo...bar>
使例如该输入:
$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV
应该变成以下输出:
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
为此,将foo和bar转换为单个字符,然后在它们之间使用这些字符的取反:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
在上面:
s/@/@A/g; s/{/@B/g; s/}/@C/g
被转换{
并}
到无法输入存在,所以这些字符,然后可转换占位符字符串foo
和bar
到。
s/foo/{/g; s/bar/}/g
被转换foo
并bar
以{
和}
分别
s/{[^{}]*}/<&>/g
正在执行我们想要的操作-转换foo...bar
为<foo...bar>
s/}/bar/g; s/{/foo/g
正在转换{
并}
返回到foo
和bar
。
s/@C/}/g; s/@B/{/g; s/@A/@/g
正在将占位符字符串转换回其原始字符。
请注意,上面的内容不依赖于输入中不存在的任何特定字符串,因为它在第一步中制造了这样的字符串,也不在乎您想要匹配的任何特定正则表达式的出现位置,因为您可以{[^{}]*}
根据需要使用多次在表达式中隔离所需的实际匹配项和/或使用seds数字匹配运算符,例如,仅替换第二个匹配项:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV