我需要在一个小 bash 脚本中替换文件中的一个字符串,但是......我得到了奇怪的结果。
假设我要替换:
<tag><![CDATA[text]]></tag>
和:
<tag><![CDATA[replaced_text]]></tag>
我应该使用sed
吗?我认为由于/
并且[
]
我得到了奇怪的结果......
解决这个问题的最佳方法是什么?
带有 -p 选项的 Perl 几乎与 sed 一样工作,并且它的正则表达式具有 \Q (引号)开关:
perl -pe 's{\Q<tag><![CDATA[text]]></tag>}
{<tag><![CDATA[replaced_text]]></tag>}' YOUR_FILE
在 Perl 中,您可以使用不同的标点符号来分隔表达式(在我的示例中为 s{...}{...})。
是的,您需要转义括号,转义斜杠或使用不同的分隔符。
sed 's,<tag><!\[CDATA\[text\]\]></tag>,<tag><!\[CDATA\[replaced)text\]\]></tag>,'
也就是说,在使用正则表达式时,SGML 和 XML 实际上并不比HTML好。不要指望这会一概而论。
这应该足够了:
$ echo '<tag><![CDATA[text]]></tag>' | sed 's/\[text\]/\[replaced_text\]/'
<tag><![CDATA[replaced_text]]></tag>
您还可以将/
sed 中的分隔符更改为不同的字符,例如,
,|
或%
.
只需使用 / 以外的分隔符,这里我使用 #:
sed -i 's#<tag><!\[CDATA\[text\]\]></tag>#<tag><![CDATA[replaced_text]]></tag>#g' filename
-i
让 sed 更改文件而不是打印出来。
g
用于匹配不止一次(全局)。
但是您是否知道要匹配的确切字符串,包括标签和文本?例如,如果您想用您的replaced_text 替换所有文本:
perl -i -pe 's#(<tag><!\[CDATA\[)(.*?)(\]\]></tag>)#\1replaced_text\3#g' filename
切换到 perl 因为 sed 不支持非贪婪乘数(*?)。