如何使用sed替换字符串的一部分

3
echo "/home/repository/tags/1.9.1/1.9.1.8/core" | sed "s/HELP/XXX/g"

我需要帮助将标签和核心之间的内容替换为“XXX”。因此,我的期望输出将是/home/repository/tags/XXX/core。

该字符串是一个目录路径,其中/home/repository/tags是唯一不变的部分。路径始终有六个级别的深度。因此,它可能不总是在标签和核心之间。


澄清一下:您想始终将路径的第四个和第五个组件替换为特定字符串吗? - Cascabel
是的 - 我可能会说超过六个组件。 - froogz3301
4个回答

3
echo "/home/repository/whatever/1.9.1/1.9.1.8/core/and/more/junk"   \
| sed 's@\(/[^/]*/[^/]*/[^/]*\)/[^/]*/[^/]*@\1/XXX@'

yields ...

/home/repository/whatever/XXX/core/and/more/junk

我喜欢使用 @ 作为分隔符。我总是忘记可以这样做。你的解决方案更加健壮。 - Rich C

2
通过使用重复量词,您可以轻松地调整替换的位置:
echo "/home/repository/tags/1.9.1/1.9.1.8/core" | \
    sed -r 's|(/([^/]+/){3})([^/]+/){2}(.*)|\1XXX/\4|'
  • 3代表需要保留的前几个组件
  • 2代表需要替换的数量

您甚至可以使用变量:

$ dirs='/one/two/three/four/five/six/seven/eight'
$ for keep in {0..3}; do for replace in {0..3}; do echo "$dirs" | \
    sed -r "s|(/([^/]+/){$keep})([^/]+/){$replace}(.*)|\1XXX/\4|"; done; done
/XXX/one/two/three/four/five/six/seven/eight
/XXX/two/three/four/five/six/seven/eight
/XXX/three/four/five/six/seven/eight
/XXX/four/five/six/seven/eight
/one/XXX/two/three/four/five/six/seven/eight
/one/XXX/three/four/five/six/seven/eight
/one/XXX/four/five/six/seven/eight
/one/XXX/five/six/seven/eight
/one/two/XXX/three/four/five/six/seven/eight
/one/two/XXX/four/five/six/seven/eight
/one/two/XXX/five/six/seven/eight
/one/two/XXX/six/seven/eight
/one/two/three/XXX/four/five/six/seven/eight
/one/two/three/XXX/five/six/seven/eight
/one/two/three/XXX/six/seven/eight
/one/two/three/XXX/seven/eight

1
如果您的目录始终是6级深度,则此方法适用(记得转义圆括号):
echo "/home/repository/tags/1.9.1/1.9.1.8/core" | 
sed 's/\(\/home\/repository\/tags\/\).*\/.*\(\/.*\)/\1XXX\2/'

产生:

/home/repository/tags/XXX/core

0

在这里,节省一些正则表达式的痛苦:

echo "/home/repository/tags/1.9.1/1.9.1.8/core" | sed 's@/home/repository/tags/.*/\(.\+\)$@/home/repository/tags/XXX/\1@'

如果你只是想剥离tags/和最后一个组件之间的所有内容,那么就不需要显式匹配组件。请注意,我使用的是+而不是*,因此该组件必须非空。这将防止出现尾随斜杠。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接