Bash脚本“&”符号创建问题

时间:2016-12-21 13:45:03

标签: bash sed

我有一个标签

<html>
<body>
<div class='a grab'>

</div>
<button class='b grab'>

</button>
</body>
</html>
<string name="currencysym">$</string> 中的

以及动态更改string.xml符号的内容。使用以下命令但不起作用:

$

获取输出:

currencysym=&#x20B9;

sed -i '' 's|<string name="currencysym">\(.*\)<\/string>|<string name="currencysym">'"<!\[CDATA\[${currencysym}\]\]>"'<\/string>|g'

“&amp;”已删除...

但我需要:

<string name="currencysym"><![CDATA[<string name="currencysym">$</string>#x20B9;]]></string>

3 个答案:

答案 0 :(得分:3)

  1. 使用xml-parser / tool来处理xml是第一选择
  2. 如果您在一行中有多个代码,则
  3. 代替<..>\(.*\)<..>更好地使用<..>\([^<]*\)<..>
  4. 替换中的
  5. &具有特殊含义,它表示模式的整个匹配(\0)。这就是为什么你看到<...>..</..>来到你的输出。如果你想要它是文字的,你应该逃避它 - &gt; \&

答案 1 :(得分:2)

第一个问题是行

currencysym=&#x20B9;

这实际上显示为“将空分配给currencysym并在后台启动没有进程”:

  • 在bash中,您可以通过执行VAR=value command来设置一个环境变量(或变量)或一个过程。这就是解释currencysym=的方式。
  • &符号表示在后台启动进程,但没有指定命令,因此没有任何反应。
  • #之后的所有内容都被解释为注释,因此{B}的观点#x20B9;只是空格。
  • 此外,;是一个命令分隔符,如&,表示“在前台运行”。这里没有使用它,因为它是#注释掉的。

您必须要转义&#;,或者只需将字符串放入单引号:currencysym=\&\#x20B9\;currencysym='&#x20B9;'

现在最重要的是,&sed中具有特殊含义,因此您需要在sed命令中使用它之前将其转义。您可以直接在currencysym=\\\&\#x20B9\;currencysym='\&#x20B9;'等定义中执行此操作,也可以在使用内置bash功能调用sed时执行此操作。而不是访问${currencysym},请参考${currencysym/&/\&}

您应该在sed命令中使用双引号来确保扩展环境变量,但是不应该在不转义感叹号的情况下对引号进行双引号。

最后,您不需要捕获原始货币符号,因为您要替换它。您应该使您的模式更具体,因为*量词是贪婪的,并且如果有多个,将转到该行的最后一个结束标记:

sed 's|<string name="currencysym">[^<]*</string>|<string name="currencysym"><![CDATA['"${currencysym/&/\&}"']]></string>|' test.xml

产量

<string name="currencysym"><![CDATA[&#x20B9;]]></string>

修改

正如@fedorqui指出的那样,您可以使用此示例来展示捕获组的正确使用。您可以捕获要完全重复的部分(标记),并按原样将它们放回输出中:

sed 's|\(<string name="currencysym">\)[^<]*\(</string>\)|\1<![CDATA['"${currencysym/&/\&}"']]>\2|' test.xml

答案 2 :(得分:1)

sed -i '' 's|\(<string name="currencysym">\)[^<]*<|\1<![CDATA[\&#x20B9;]]><|g' YourFile
  • 您保存在缓冲区中的组是您的代码中的错误组,我保留第一部分而不是&
  • .*进行分组与您需要的所有非首先<不同。特别是使用g选项意味着可能会发生几次出现,在这种情况下,第一个字符串名称和最后一个 之间的连接是中间部分(您的组)。
  • 单独使用&(未转义)的carrefull,表示替换部分中的“整个搜索模式查找”