我有一个 XML 文件,其中包含,<asd>blablabla</asd>
以及
<dsa>-some stuff
-other stuff
final stuff.</dsa>
我想用“dsa”标签之间的任何内容替换“asd”标签之间的所有内容,这几乎 100% 是多行的。我不想替换标签本身,只想替换它们之间的文本并保留换行符。
该文件会不时发生变化,它的名称、扩展名和标签将保持不变,只有它们之间的内容会发生变化。
我需要一个可以在基本的、裸露的 bash(Github Actions 使用的那种)上实现此目的的命令。
我正在考虑sed
,但我不知道如何告诉它用多行替换。
编辑:
我的错误(也许?)我的文件实际上是一个 .net csproj 文件,而不是真正的 XML 文件,所以我不确定类似的命令是否xmlstarlet
可以使用它。
答案1
假设一个格式良好的 XML 文档:
<root>
<asd>blablabla</asd>
<dsa>-some stuff
-other stuff
final stuff.</dsa>
</root>
您可以简单地使用该节点xmlstarlet
的内容替换顶级asd
节点的内容,dsa
如下所示:
$ xmlstarlet ed -u '/root/asd' -x '/root/dsa/text()' file.xml
<?xml version="1.0"?>
<root>
<asd>-some stuff
-other stuff
final stuff.</asd>
<dsa>-some stuff
-other stuff
final stuff.</dsa>
</root>
asd
一个更复杂的示例,需要用其兄弟节点替换每个节点dsa
:
<?xml version="1.0"?>
<root>
<node1>
<asd>blablabla</asd>
<dsa>-some stuff
-other stuff
final stuff.</dsa>
</node1>
<node2>
<asd>REPLACE ME</asd>
<dsa>REPLACE WITH THIS</dsa>
</node2>
</root>
这可以通过以下方式完成
$ xmlstarlet ed -u '//asd' -x '../dsa/text()' file.xml
<?xml version="1.0"?>
<root>
<node1>
<asd>-some stuff
-other stuff
final stuff.</asd>
<dsa>-some stuff
-other stuff
final stuff.</dsa>
</node1>
<node2>
<asd>REPLACE WITH THIS</asd>
<dsa>REPLACE WITH THIS</dsa>
</node2>
</root>
答案2
这个问题之前已经回答过:如何使用 sed 替换多行字符串?
但我强烈建议该帖子中的第二个答案:使用perl
.许多人可能会远离 PERL,但它最初的用途正是用于类似这样的事情。
$ perl -0777 -i.original -pe 's/a test\nPlease do not/not a test\nBe/igs' alpha.txt
正如您所看到的,您的模式中允许换行。请参阅答案以了解更多详细信息。
答案3
如果xmlstarlet
是一个选项 - 也许通过这个xmlstarlet GitHub 操作- 然后给出
$ cat file.xml
<?xml version="1.0"?>
<foo>
<asd>blablabla</asd>
<dsa>-some stuff
-other stuff
final stuff.</dsa>
</foo>
你可以做类似的事情
$ xmlstarlet edit --update '//asd' --value "$(xmlstarlet select -t -v '//dsa' file.xml)" file.xml
<?xml version="1.0"?>
<foo>
<asd>-some stuff
-other stuff
final stuff.</asd>
<dsa>-some stuff
-other stuff
final stuff.</dsa>
</foo>
参考:
答案4
好吧,好吧,我们应该使用 XML 感知解析器。但对于 Perl:
perl -0pe 'm!<dsa>(.*?)</dsa>!s and $a=$1;
s!<asd>.*?</asd>!<asd>$a</asd>!s' example