sed:具有反向前瞻匹配的嵌套组
sed: Nested group with inverse lookahead matching
我正在尝试用图片 bar
替换除 URL 之外的所有 URL 的图片标签。但是,它说正则表达式无效。
仅检查 regex101.com 上的正则表达式 (image:(?!.*bar).*:).*
看起来不错。将 sed 表达式的第二部分替换为组 (image:(?!.*bar).*:)
.
时出现错误
$ echo '
image: mydomain/subdomain/foo:old_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:old_tag
' | sed --regexp-extended "s|(image:(?!.*bar).*:).*|new_tag|g"
sed: -e expression #1, char 36: Invalid preceding regular expression
预期的最终结果是:
image: mydomain/subdomain/foo:new_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:new_tag
正则表达式的解释(image:(?!.*bar).*:).*
搜索所有包含 image:.*:.*
的行,但包含 image:.*bar
的行除外
POSIX ERE 仍然不支持环视。幸运的是,你可以匹配特定模式的一行并跳过它,然后匹配你需要的任何内容:
sed -E "/image:.*bar/!s/(image:.*:).*/new_tag/"
参见 online demo:
echo '
image: mydomain/subdomain/foo:old_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:old_tag
' | sed -E "/image:.*bar/!s/(image:.*:).*/new_tag/"
输出:
image: mydomain/subdomain/foo:new_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:new_tag
这可能适合您 (GNU sed):
sed -E 's/^/\n/
:a;ta
s/\n(image: \S*bar\S*)/\n/;ta
s/\n(image: \S*:)\S*/new_tag\n/;ta
s/\n(.)/\n/;ta
s/\n$//' file
一次处理一行。
在行首引入换行符。
如果换行符后面的字符串是包含bar
的图片,跳过它,移动换行符并重复。
如果换行符后面的字符串是没有bar
的图像,用新标签替换它,移动换行符并重复。
否则,将换行符移到下一个字符并重复。
当换行不能再移动时,将其移除,打印当前行并重复。
N.B。不能使用替换命令的 g
标志,因为必须单独比较图像的每个实例。如果每行只有一张图片,那么使用@Wiktor Stribiżew 解决方案。
我正在尝试用图片 bar
替换除 URL 之外的所有 URL 的图片标签。但是,它说正则表达式无效。
仅检查 regex101.com 上的正则表达式 (image:(?!.*bar).*:).*
看起来不错。将 sed 表达式的第二部分替换为组 (image:(?!.*bar).*:)
.
$ echo '
image: mydomain/subdomain/foo:old_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:old_tag
' | sed --regexp-extended "s|(image:(?!.*bar).*:).*|new_tag|g"
sed: -e expression #1, char 36: Invalid preceding regular expression
预期的最终结果是:
image: mydomain/subdomain/foo:new_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:new_tag
正则表达式的解释(image:(?!.*bar).*:).*
搜索所有包含 image:.*:.*
的行,但包含 image:.*bar
POSIX ERE 仍然不支持环视。幸运的是,你可以匹配特定模式的一行并跳过它,然后匹配你需要的任何内容:
sed -E "/image:.*bar/!s/(image:.*:).*/new_tag/"
参见 online demo:
echo '
image: mydomain/subdomain/foo:old_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:old_tag
' | sed -E "/image:.*bar/!s/(image:.*:).*/new_tag/"
输出:
image: mydomain/subdomain/foo:new_tag
image: mydomain/subdomain/bar:dont_update_me_tag
image: mydomain/subdomain/baz:new_tag
这可能适合您 (GNU sed):
sed -E 's/^/\n/
:a;ta
s/\n(image: \S*bar\S*)/\n/;ta
s/\n(image: \S*:)\S*/new_tag\n/;ta
s/\n(.)/\n/;ta
s/\n$//' file
一次处理一行。
在行首引入换行符。
如果换行符后面的字符串是包含bar
的图片,跳过它,移动换行符并重复。
如果换行符后面的字符串是没有bar
的图像,用新标签替换它,移动换行符并重复。
否则,将换行符移到下一个字符并重复。
当换行不能再移动时,将其移除,打印当前行并重复。
N.B。不能使用替换命令的 g
标志,因为必须单独比较图像的每个实例。如果每行只有一张图片,那么使用@Wiktor Stribiżew 解决方案。