用sed替换两个模式之间的字符串 - 没有错误,没有结果

时间:2016-12-14 17:31:36

标签: regex bash sed

我要更改用户名的文件示例:

<host><![CDATA[localhost]]></host>
<username><![CDATA[root]]></username>

Here is my regex test以确保匹配。

最后sed命令完成且没有错误,并且不会改变任何内容:

sed -i -e 's/(<username><!\[CDATA\[).*(\]\]><\/username>)/TEST/g' path/to/file.xml

这应该是结果:

<host><![CDATA[localhost]]></host>
TEST

除了它根本不替换之外,我需要它像这样工作,以便在前后保留捕获组,实际上只替换用户名:

sed -i -e 's/(<username><!\[CDATA\[).*(\]\]><\/username>)/\1TEST\2/g' path/to/file.xml

但是会返回此错误:

sed: -e expression #1, char 57: invalid reference \2 on `s' command's RHS

所以我认为捕捉群体在某种程度上是松散匹配的,因为它并没有真正捕捉它们,这使得替换不会取代任何东西?

我想要的最终结果是:

<host><![CDATA[localhost]]></host>
<username><![CDATA[TEST]]></username>

3 个答案:

答案 0 :(得分:0)

可能更精致的awk解决方案:

 awk '{if ($0 ~ /username/) gsub(/CDATA\[.+\]/, "CDATA[TEST]"); print $0 }' file.txt

用语言说:

如果该行包含用户名,则使用CDATA [TEST]将所有CDATA []实例分出。这将改变这条线。然后打印每一行。如果需要,可以更多地改进正则表达式。

答案 1 :(得分:0)

awk '{sub(/root/,"TEST")}1' file

<host><![CDATA[localhost]]></host>
<username><![CDATA[TEST]]></username>

答案 2 :(得分:0)

您没有任何捕获组-您需要使用(..)或(在GNU sed中)添加-r选项以使用扩展正则表达式语法。                     –́Toby Speight

我只是不知道扩展的正则表达式。这就是我的SED现在在循环中的样子:
sed -i -r -e 's/(<'"$key"'><![CDATA[).*(]]><\/'"$key"'>)/\1'"${db_local[$key]}"'\2/g' ${path_local[site]}/path/to/file.xml                     – a_rts