从文件A复制并使用sed

时间:2017-08-09 15:37:30

标签: regex sed

我有两个XML文件,我想

  1. 在文件A中找到特定的XML节点
  2. 复制
  3. 在文件B中找到特定部分
  4. 粘贴复制的节点。
  5. 已经在我的机器上使用了sed,但我在找到正确的正则表达式配置方面遇到了麻烦。

    文件A的示例:

    <Containers>
      <Container id="1">    <-- to be copied start
        blubb
      </Container>    <-- to be copied end
      <Container id="2">blobb</Container>
    </Containers>
    

    文件B的示例:

    <Containers>
      <Container id="99">blibb</Container>
    </Containers>
    

    <Container id="1"切换到</Container>所需的输出文件B的示例:

    <Containers>
      <Container id="1">    <-- copied here start
        blubb
      </Container>    <-- copied here end
      <Container id="99">blibb</Container>
    </Containers>
    

    我知道它会更清晰,也许更容易使用XML解析器和其他工具,但我需要使用sed,我不是一个非常有经验的sed / regex用户。我只是用“替代”和“删除”玩了一下,但这就是......

    我可以澄清一下:

    • 我需要使用sed,因为这是该机器上唯一可用的工具。
    • 我知道,我可以用其他编程语言和其他工具完成此操作,但这不可能。运行的机器不在我的控制之下!

    我知道我不应该将正则表达式用于XML / XHTML - 我知道但是地球要复杂得多。

    我是从cygwin运行的。

    更新1:

    由于多次回复,似乎无法找到sed的解决方案。感谢所有理解问题的人并试图提供帮助!

    如果有人仍然看到了潜在的解决方案,请告诉我。但挑战在于使用sed。我使用了带有boost,QT,C#,Java等的XML解析器......但这不是问题,如果我可以选择......我不能。

    更新2:

    谢谢大家,特别是Benjamin W.绝对有可能使用sed来解决这个问题,但正如很多次所说,如果你有可能使用xml解析lib和其他技术那么这应该是通往去。

    对我来说,使用现有的技术解决方案解决了非技术问题(伪安全指南)。

    这是我的最终解决方案:

    sed "/<Container id=\"1\">/,/<\/Container>/!d" fileA.xml | ^
    sed -i "/<Containers>/r /dev/stdin" fileB.xml
    

    谢谢。

1 个答案:

答案 0 :(得分:5)

这是一个sed命令,它执行示例要求的操作。让我先介绍一下,然后列出它将如何破解:

sed '/<Container id="1">/,/<\/Container>/!d' fileA.xml |
    sed '/<Containers>/r /dev/stdin' fileB.xml

导致

<Containers>
  <Container id="1">
    blubb
  </Container>
  <Container id="99">blibb</Container>
</Containers>

这要求GNU sed从特殊文件/dev/stdin读取标准输入;如果没有GNU sed,第一个命令的输出可以保存到临时文件中,然后从那里读取。

第一个命令查找以匹配<Container id="1">的行开头并以匹配<\/Container>的行结束的行范围。该范围的的所有内容都将被删除。

第二个命令查找匹配<Containers>的行,然后使用r插入第一个命令的输出。

这是如何打破的:

  • 空格中的任何更改(<Container id="1">并且中断)
  • 换行符的任何差异
    • 与开始标记位于同一行的关闭标记:中断
    • <Containers>本身不在一条线上:中断
    • 下一个节点与结束标记</Container>在同一行开始:中断
  • ID为其他地方的任何<Container>子节点
  • <Containers>
  • 中的任何其他fileB.xml节点
  • 任何具有相同节点名称的嵌套

......还有更多。

正如评论中所指出的,这应该是最后的手段。最好将输入文件复制到有合适工具的机器上,然后将其复制回使用它,而不是使用它。