我正在尝试替换 XML 文件中的字符串。
从
<hello="value" exampleno="xxxx:yyyyyyyy/dd=eeeee-ffffff,aa=bb ccc,dd=eeee,ff=gggg,hh=iii,jj=kkk,ll=mmmm" />
我只想更换
aa=bb ccc,dd=eeee
与
xx=yy yyy,zz=aaaa,bb=cc ddd
如何实现这一目标?谢谢
答案1
假设 XML 格式良好,如下所示:
<?xml version="1.0"?>
<root>
<hello exmapleno="Other attribute's value"/>
<hello exampleno="xxxx:yyyyyyyy/dd=eeeee-ffffff,aa=bb ccc,dd=eeee,ff=gggg,hh=iii,jj=kkk,ll=mmmm"/>
</root>
...那么您可以使用 替换节点中属性值的aa=bb ccc,dd=eeee
一部分,如下所示:exampleno
hello
xmlstarlet
xmlstarlet edit \
--var searchstring '"aa=bb ccc,dd=eeee"' \
--var replacement '"xx=yy yyy,zz=aaaa,bb=cc ddd"' \
--update '//hello/@exampleno[contains(.,$searchstring)]' \
--expr 'concat(
substring-before(.,$searchstring),
$replacement,
substring-after(.,$searchstring)
)' file.xml
(请注意,--var
变量是 Xpath 表达式,因此字符串必须包含文字双引号。)
或者,XPath 表达式中没有花哨的变量:
xmlstarlet edit \
--update '//hello/@exampleno[contains(.,"aa=bb ccc,dd=eeee")]' \
--expr 'concat(
substring-before(.,"aa=bb ccc,dd=eeee"),
"xx=yy yyy,zz=aaaa,bb=cc ddd",
substring-after(.,"aa=bb ccc,dd=eeee")
)' file.xml
这将修改全部 hello
文档中包含exampleno
带有搜索字符串的属性的节点。您是否想要手动选择这些节点之一,然后使用比//hello
.
该命令的作用是定位所有与XPath 表达式匹配的节点//node/@exampleno
(即exampleno
所有hello
节点的属性),附加条件是该值必须包含搜索字符串。然后它根据表达式更新匹配属性的值--expr
。该表达式挑选出属性值中目标字符串(第一次出现)之前和之后的部分,并将它们与中间的新字符串连接起来。
输出被写入终端,但您将使用适当命名的选项进行就地编辑--inplace
。
测试运行,使用缩短的选项名称:
$ xmlstarlet ed --var s '"aa=bb ccc,dd=eeee"' --var r '"xx=yy yyy,zz=aaaa,bb=cc ddd"' -u '//hello/@exampleno[contains(.,$s)]' -x 'concat(substring-before(.,$s),$r,substring-after(.,$s))' file.xml
<?xml version="1.0"?>
<root>
<hello exmapleno="Other attribute's value"/>
<hello exampleno="xxxx:yyyyyyyy/dd=eeeee-ffffff,xx=yy yyy,zz=aaaa,bb=cc ddd,ff=gggg,hh=iii,jj=kkk,ll=mmmm"/>
</root>
答案2
我假设您不想安装,xmlstarlet
因为您问过同样的问题在这里再次出现提到你只需要 unix 命令。
首先:
同样的问题不要问两次!
只需使用注释来提及您想以另一种方式执行此操作即可。
我假设您提到“unix 命令”,因为您不想安装额外的软件。
如今,大多数基于 UNIX 的操作系统已经在基本安装中包含 Perl,因此您可以这样做:
perl -pne 's/aa=bb ccc,dd=eeee/xx=yy yyy,zz=aaaa,bb=cc ddd/' < file.xml > file2.xml
无需安装额外的软件。