我有一个包含以下内容的文件:
<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>