在单行的两个图案之间打印

在单行的两个图案之间打印

我有一个包含以下内容的文件:

<alarm="yes">
<moduleId>aaa</moduleId>
<documentation>
<description>bbb</description>
<Object>ccc</Object>
</documentation>
</alarmSpecification>
<alarm="yes">
<moduleId>bbb</moduleId>
<documentation>
<description>abc</description>
<Object>xxx</Object>
</documentation>
</alarmSpecification>

我想匹配图案并在一行中打印。这里,模式是alarm&alarmSpecification输出将是这样的

<alarm="yes">,<moduleId>aaa</moduleId>,<documentation>,<description>bbb</description>,<Object>ccc</Object>,</documentation>,</alarmSpecification>
<alarm="yes">,<moduleId>aaa</moduleId>,<documentation>,<description>bbb</description>,<Object>ccc</Object>,</documentation>,</alarmSpecification>

请指导如何实现它。

答案1

由于这似乎不是有效的 XML,因此最好也使用通用文本处理,例如sed

sed 'H;/<alarm=/h;/<\/alarmSpecification>/!d;g;s/\n/,/g'
  • H将行追加到H旧空间
  • /<alarm=/h重置新<alarm字段中收集的行
  • /<\/alarmSpecification>/!d如果这不是警报则停止指定行
  • 否则,将保留空间中收集的 ilnes与 替换为g换行符,s/\n/,/g

答案2

使用awk

$ awk '/<alarm/,/<\/alarmSpecification/{ORS = (/<\/alarmSpecification>/) ? "\n" : "," ;print}' file

答案3

这确实应该使用 XML 解析器来完成。下面的解决方案适用于您的示例,但在任何稍微复杂的情况下都会失败。使用像我在这里建议的那样简单的方法来解析 XML 等复杂格式并不是一个好主意。话虽如此,这是一种丑陋、脆弱的方法,只能保证适用于您展示的具体、简单的示例:

$ perl -ne '$k=1 if /<alarm=/; $k=0 if /<\/alarmSpecification>/; s/\n/,/ if $k; print $k ? $_ : "\n"; ' file | sed 's/,$//'
<alarm="yes">,<moduleId>aaa</moduleId>,<documentation>,<description>bbb</description>,<Object>ccc</Object>,</documentation>
<alarm="yes">,<moduleId>bbb</moduleId>,<documentation>,<description>abc</description>,<Object>xxx</Object>,</documentation>

答案4

使用 GNU awk 进行多字符 RS:

$ awk -v RS='</alarmSpecification>\n' -v ORS= -F'\n' -v OFS=',' '{$NF=$NF RT} 1' file
<alarm="yes">,<moduleId>aaa</moduleId>,<documentation>,<description>bbb</description>,<Object>ccc</Object>,</documentation>,</alarmSpecification>
<alarm="yes">,<moduleId>bbb</moduleId>,<documentation>,<description>abc</description>,<Object>xxx</Object>,</documentation>,</alarmSpecification>

相关内容