用多行字符串替换文件中的文本

用多行字符串替换文件中的文本

我有一个 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

相关内容