如何在 `sed` 中(例如,没有 PREFIXPREFIX)仅在路径前添加一次前缀(以幂等方式)?

How to prepend a PREFIX to paths only once (in an idempotent way) in `sed` (e.g., no PREFIXPREFIX)?

我有一个包含复杂多行命令和一些不相关文本的文件。我需要在某些路径(例如 /foo)前加上前缀 /bar。该脚本可以 运行 多次,但不得在同一路径前添加多个 /bar 前缀。例如,运行脚本一次得到/bar/foo,运行再次得到,而仍然得到/bar/foo,而不是[=16] =]. 为了与现有代码库保持一致,我必须使用 sed

我想出了想要的结果(如下),但我的方法似乎很麻烦。有没有更好的(更短、更少重复)的方式?

$ echo '/foo' > infile
$ cat infile 
"/foo" /foo

# Replace once, change expected:
$ sed -i '\#bar/foo#!s#\(/foo\)#/bar#g' infile
$ cat infile 
"/bar/foo" /bar/foo

# Replace twice - no change expected:
$ sed -i '\#bar/foo#!s#\(/foo\)#/bar#g' infile
$ cat infile 
"/bar/foo" /bar/foo

编辑:不要使用我的“解决方案”:在重要的边缘情况下它是错误的,请参阅下面的评论

您可以将此 sed 解决方案与可选组一起使用,以将 /foo 替换为 /bar/foo,但当 /bar 已经存在时跳过匹配:

sed -E 's~(/bar)?(/foo)~/bar~g' file

RegEx Demo

详情:

  • (/bar)?:在捕获组 #1
  • 中匹配 可选 /bar
  • (/foo):在捕获组 #2
  • 中匹配 /foo
  • /bar:替换为始终将 /bar 后跟我们在捕获组 #2
  • 中捕获的值