Bash - 引用变量扩展与sed混合产生不良替代

时间:2013-07-03 09:35:11

标签: bash sed

我有这个sed oneliner的问题

sed -i -n "1h; 1!H; ${g; :a s/\(Name=\"$key\".*<\!\[CDATA\[\"\)$val\(\"\]\]>\)/\1$deval\2/;ta p}"

显然,我需要在sed中扩展变量keyvaldeval。所以我需要"周围的sed命令。

使用此命令我得到

bash: !H: event not found

转义!纠正它

sed -i -n "1h; 1\!H; ${g; :a s/\(Name=\"$key\".*<\!\[CDATA\[\"\)$val(\"\]\]>\)/\1$deval\2/;ta p}"

有了这个,我得到了

bash: sed -i -n "1h; 1\!H; ${g; :a s/\(Name=\"$key\".*<\!\[CDATA\[\"\)$val\(\"\]\]>\)/\1$deval\2/;ta p}" :bad substitution

所以我猜{是个问题。试图像这样修复它

sed -i -n "1h; 1\!H; $\{g; :a s/\(Name=\"$key\".*<\!\[CDATA\[\"\)$val(\"\]\]>\)/\1$deval\2/;ta p}"

产量

sed: -e expression 1, char 6: unknown command: "\"

这里发生了什么?我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:4)

event not found只是交互式shell中的一个问题,因为默认情况下会启用histexpand。如果您先运行set +H或将其放入脚本并从那里运行,Bash将单独留下!个。

${..}是变量替换语法(因此错位值会给出bad substitution)。让sed通过转义$将其视为要在最后一行执行的命令块,如\${ .. }中所示。

完整:

set +H
key="foo"
val="bar"
deval="puppies"
echo 'Name="foo" <![CDATA["bar"]]>' > file
sed -i -n "1h; 1!H; \${g; :a s/\(Name=\"$key\".*<!\[CDATA\[\"\)$val\(\"\]\]>\)/\1$deval\2/;ta p}" file
cat file

将打印Name="foo" <![CDATA["puppies"]]>

答案 1 :(得分:2)

您可以使用单独的单引号字符串:

sed -i -n '1h; 1!H; ${g; :a s/\(Name='"$key"'.*<\!\[CDATA\[\"\)'"$val"'\(\"\]\]>\)/\1'"$deval"'\2/;ta p}'