尽管我使用 grep 可以轻松找到相同的字符串,但我很难使用 sed 替换 XML 文件中的文本字符串。由于要替换的新字符串和旧字符串包含大量特殊字符,我认为最好将它们存储在变量中,而不是使用大量反斜杠:
OLD_STRING='<property name="webServiceHost">${jboss.bind.address}</property>'
NEW_STRING='<!--<property name="webServiceHost">${jboss.bind.address}</property>-->'
字符串似乎按预期存储:
$ echo $OLD_STRING; echo $NEW_STRING
<property name="webServiceHost">${jboss.bind.address}</property>
<!--<property name="webServiceHost">${jboss.bind.address}</property>-->
通过 Grep 确认旧字符串存在于 XML 文件中:
$ grep "$OLD_STRING" jboss-beans.xml
<property name="webServiceHost">${jboss.bind.address}</property>
但是以下 sed 命令不产生任何输出:
sed -i 's/"$OLD_STRING"/"$NEW_STRING"/g' jboss-beans.xml
知道我这里遗漏了什么吗?
答案1
将 shell 变量放在单引号中会禁用它们的解释。这就是您的命令无效的原因。
$ echo 's/"$OLD_STRING"/"$NEW_STRING"/g'
s/"$OLD_STRING"/"$NEW_STRING"/g
应该这样写:
sed -i "s/'$OLD_STRING'/'$NEW_STRING'/g" jboss-beans.xml
但随后变量被解释前调用sed
并且再次包含特殊字符:
$ echo "s/'$OLD_STRING'/'$NEW_STRING'/g"
s/'<property name="webServiceHost">${jboss.bind.address}</property>'/'<!--<property name="webServiceHost">${jboss.bind.address}</property>-->'/g
因此,sed
有这个特殊功能允许s///
通过简单地使用命令分隔符来定义命令分隔符,例如:
sed -i "s#'$OLD_STRING'#'$NEW_STRING'#g" jboss-beans.xml
但是您的搜索表达式包含特殊的正则表达式字符,这样使用sed
只是浪费它的能力。我会像这样写表达式:
sed -i 's/\(<.*webServiceHost.*jboss.bind.address.*>\)/<!--\1-->/' jboss-beans.xml
当然,您可以根据需要使匹配字符串更具体或更不具体。还有其他不错的功能可以提供帮助。sed
允许将编辑操作缩小到与特定模式匹配的行。您的命令可能如下所示:
sed -i '/webServiceHost/ s/^\(.*\)$/<!--\1-->/' jboss-beans.xml
答案2
这可能对你有用:
命令行 XML 操作
http://xmlstar.sourceforge.net/
AFAICR
apt-get 安装 xmlstarlet