【问题标题】:edit xml file using sed or something by matching over multiple lines使用 sed 或通过匹配多行来编辑 xml 文件
【发布时间】:2020-09-21 11:50:17
【问题描述】:

我想“编辑”一些 xml 文件,这些文件可能在一个文件中多次包含类似的部分。 我需要在每个部分中添加 2 条可能的缺失行(我称之为一对)。即检查“对”是否存在,如果不存在则添加它们。

例如下面是我想添加的可能缺少的对行。

<arg>--possibleMissedKey</arg>
<arg>possibleMissedValue</arg>

下面的文件有这对,所以我不需要添加它们 但是如果任何部分确实错过了这对,我想将这对添加到该部分中。而且每个部分中的行数也是不可预测的。


    <some-tag-section-not-interesting>
        some contents not interesting to me
    </some-tag-section-not-interesting>
    <some-tag-to-look-for>
        <some stuff - a> ..... </some stuff - a>
        <arg>--possibleMissedKey</arg>
        <arg>possibleMissedValue</arg>
        <something-else-not-interesting>blahblah</something-else-not-interesting>
    </some-tag-to-look-for>
    <some-tag-to-look-for>
        <some stuff - b>....</some stuff - b>
        <arg>--possibleMissedKey</arg>
        <arg>possibleMissedValue</arg>
        <something-else-not-interesting>blahblah</something-else-not-interesting>
    </some-tag-to-look-for>

所以我考虑了几个选项,但每个选项我都有一个问题:

  • 我首先想到的是“sed”。我希望替换结束标签 &lt;/some-tag-to-look-for&gt;

        <arg>--possibleMissedKey</arg>
        <arg>possibleMissedValue</arg>
     </some-tag-to-look-for> 

即基本上将其添加到该部分的最后一部分。 但我不知道我是否可以在 sed 中“多行模式匹配”。而且我没有使用所谓的“保持空间”。 我使用 sed 的经验是检查“当前单行”中的一些字符串。

  • 我希望检查的另一个选项是引入inside_a_section_flag,初始值为“0”。开始阅读文件,当我发现盯着&lt;some-tag-to-look-for&gt; 的那一刻,我把inside_a_section_flag 变成'1', 一旦我到达'结尾&lt;/some-tag-to-look-for&gt;',我会做一些可能的改变,然后把它变回'0'。 所以这个inside_a_section_flag,如果是1,意味着我在这个部分里面......所以我需要寻找'pair', 如果我找到了这对,我将inside_a_section_flag 变为 1,这意味着我不需要添加这对并且可以退出当前部分.... 但我不知道sed 是否也可以使用变量标志,即根据变量值进行条件替换/更改

  • 这完全应该由 shell 来完成,而应该由 python 脚本来完成?

【问题讨论】:

  • 我小时候曾经很喜欢 sed,现在它仍然是我最喜欢的工具之一处理琐碎的任务。它可以用于中等复杂度的任务,但 sedscript 很快就会变得相当神秘。相当高效,但编写、阅读和维护都很糟糕。正如你想要的 1. 解码一个 xml 文件 2. 测试另一个标签中是否存在一个标签 3. 添加一个标签以确保保留 XML 语法,我会在这里使用 Python,它支持带有 xml.etree 的 XML模块。不过只是我的意见(因此发表评论)

标签: python bash sed


【解决方案1】:

这可能对你有用(GNU sed):

sed '/<some-tag-to-look-for>/{:a;n;/<arg>--possibleMissedKey<\/arg>/b;/<\/some-tag-to-look-for>/!{h;ba};x;s/\S.*/<arg>--possibleMissedKey<\/arg>/p;s//<arg>--possibleMissedValue<\/arg>/p;x}' file

匹配包含&lt;some-tag-to-look-for&gt;的行。

遍历以下几行。

如果遇到包含&lt;arg&gt;--possibleMissedKey&lt;/arg&gt; 的行,请退出。

否则,如果当前行与&lt;/some-tag-to-look-for&gt;不匹配,则复制并重复。

找到结束标签后,以复制的行为模板插入需要的两行(以保留缩进)。

【讨论】:

  • 这项工作就像一个魅力。我必须去学习你答案中的所有 sed 命令,并尝试进一步了解 sed....
  • @MinnieShi 请参阅here 了解更多 sed 信息
  • 嗨@potong,在阅读了“unix in a nutshell book”中的 sed 命令后,我想我几乎理解了上述答案中的所有内容。唯一的事情不能从书上找到答案是\S.* 部分。替代命令中的这种模式是什么?我知道它应该遵循s/pattern/replacement/ 的格式...即s/\S.*/&lt;arg&gt;--possibleMissedKey&lt;\/arg&gt;/ 试图查找然后替换是什么。
  • @Minnie 替换的 LHS 匹配第一个非空白字符到行尾,有关正则表达式扩展的更多信息,请参阅 here
猜你喜欢
  • 2015-09-20
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 2015-05-21
  • 2011-03-16
  • 2015-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多