解析 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
有关我要实现的目标的一些背景信息。
目前我在一个锁定的 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