解析 xml 并将数据提取到 table 中的最有效方法

Most efficient way to parse xml and extract data into a table

有关我要实现的目标的一些背景信息。

目前我在一个锁定的 HPUX 盒子上使用 bash 和 perl,但是我没有使用 perl 的经验。

输入是十六进制和 xml 的转储,格式如下(0 到 n):

MQGET of message number 1

Message Descriptor
Various Config / Params
Various Config / Params
Various Config / Params

Message

length - 3631 bytes

00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'

00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<config  params>'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<soapenv:Envelop'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        'e xmlns:soapenv='
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '"http://schemas.'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'

00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<useful_xml_data'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        '<xml_data_closin'
00000000:   3453 5675 2346 2345 2346 8679 3452 7554        'g_tag>          '

我想得到以下输出:

1 <useful_xml_data> <specific_value> <specific_xml>
2 <useful_xml_data> <specific_value> <specific_xml>
n <useful_xml_data> <specific_value> <specific_xml>

我目前的做法如下:

untouchable_script_sdout | sed -n "/^[0000]/p" | cut -c59-74 | tr -d '\n'

这将去除除 xml 之外的所有内容并删除所有换行符。

然后我通过一个类似于 post 的 xml 解析脚本传递它,它在实体等于 xml 结束标记时添加 \n。

这给我留下了以下内容:

<msg1_open_tag>
<xml_tag>value
</xmltag>
<xml_tag>value
</xmltag>
....
</close_tag>

<msgn_open_tag>
<xml_tag>value
</xmltag>
<xml_tag>value
</xmltag>
</close_tag>
....

这意味着我可以使用 grep/awk 提取我想要的数据,但是我很难对齐数据(一些消息可能有空值)。

在我看来,下一步是让每条消息在一行中显示 xml:

<msg1_open_tag>  <xml_tag>value  </xmltag>  <xml_tag>value  </xmltag>    </close_tag>
<msgn_open_tag>   <xml_tag>value   </xmltag>   <xml_tag>value   </xmltag>   </close_tag>

根据需要循环处理和打印以获得 table。

但是我很难将每条消息都放在一行中。

你可以肯定地说,我远不是 bash 专家,我只是边走边学。

如有任何建议或最佳实践建议,我们将不胜感激。

您可以使用 sed 将数据与 mikeserv 对另一个 question 的回答中解释的技巧对齐:

sed '/open_tag/,/close_tag/{H;$!d};x;s/\n/  /g'

此外,

sed -n "/^[0000]/p"

只匹配第一个零,因为 [list] 匹配列表中的单个字符,所以将括号去掉可能会完成您对该步骤的预期。

不幸的是,我无法使用建议的 sed 命令。

经过几个小时的修补和大量 Google-Fu 我想出了以下内容:

#par_xml is a modified version from mikeserv's answer which was linked above
#awk 'NR%4 !=0' is to remove a duplicate value (constant on every message)

par_xml.sh app_xml.out | grep –E "UsefulXML1|UsefulXML2|UsefulXML3|UsefulXML4" | grep –v "</" | awk –F'>' '{print }' | awk 'NR%4 !=0' | sed 'N;N;N;s/\n/ /g'

是的,我知道这个解决方案有多糟糕......但它让我得到了想要的输出:

useful_xml_data1 specific_value1 specific_xml1 useful_xml_data1
useful_xml_data2 specific_value2 specific_xml2 useful_xml_data2
useful_xml_datan specific_valuen specific_xmln useful_xml_datan