如何用xmlstarlet将分隔符从空格改为逗号提取XML数据?
问题描述
我正在解析以下XML文件:
<?xml version="1.0" encoding="ISO-8859-1"?> <detection-run> <wireless-network> <SSID> <essid>first</essid> </SSID> <BSSID>12:34:56:78:90</BSSID> <wireless-client number="1"> <client-mac>A0:CD:EF:GH:IJ</client-mac> </wireless-client> <wireless-client number="2"> <client-mac>A1:CD:EF:GH:IJ</client-mac> </wireless-client> <wireless-client number="3"> <client-mac>A2:CD:EF:GH:IJ</client-mac> </wireless-client> <wireless-client number="4"> <client-mac>A3:CD:EF:GH:IJ</client-mac> </wireless-client> </wireless-network> <wireless-network> <SSID> <essid>second</essid> </SSID> <BSSID>98:76:54:32:10</BSSID> <wireless-client number="1"> <client-mac>B0:CD:EF:GH:IJ</client-mac> </wireless-client> <wireless-client number="2"> <client-mac>B1:CD:EF:GH:IJ</client-mac> </wireless-client> <wireless-client number="3"> <client-mac>B2:CD:EF:GH:IJ</client-mac> </wireless-client> <wireless-client number="4"> <client-mac>B3:CD:EF:GH:IJ</client-mac> </wireless-client> </wireless-network> </detection-run>
我想用xmlstarlet提取essid、BSSID和客户端MAC地址,要求客户端MAC以逗号分隔。尝试了几种命令都没得到预期结果:
- 使用
concat的命令仅能提取第一个客户端:
list=$(xmlstarlet sel -T -t -m '/detection-run/wireless-network' -v 'SSID/essid' -o "|" -v 'BSSID' -o "|" -v "concat(wireless-client/client-mac, ',')" -n xmll-02.kismet.netxml)
输出:
first|12:34:56:78:90|A0:CD:EF:GH:IJ, second|98:76:54:32:10|B0:CD:EF:GH:IJ,
- 移除
concat后能列出所有客户端,但用空格分隔:
list=$(xmlstarlet sel -T -t -m '/detection-run/wireless-network' -v 'SSID/essid' -o "|" -v 'BSSID' -o "|" -v 'wireless-client/client-mac' -n xmll-02.kismet.netxml)
输出:
first|12:34:56:78:90|A0:CD:EF:GH:IJ A1:CD:EF:GH:IJ A2:CD:EF:GH:IJ A3:CD:EF:GH:IJ second|98:76:54:32:10|B0:CD:EF:GH:IJ B1:CD:EF:GH:IJ B2:CD:EF:GH:IJ B3:CD:EF:GH:IJ
- 添加
-o ","只会在末尾加逗号,仍为空格分隔:
list=$(xmlstarlet sel -T -t -m '/detection-run/wireless-network' -v 'SSID/essid' -o "|" -v 'BSSID' -o "|" -v 'wireless-client/client-mac' -o "," -n xmll-02.kismet.netxml)
输出:
first|12:34:56:78:90|A0:CD:EF:GH:IJ A1:CD:EF:GH:IJ A2:CD:EF:GH:IJ A3:CD:EF:GH:IJ, second|98:76:54:32:10|B0:CD:EF:GH:IJ B1:CD:EF:GH:IJ B2:CD:EF:GH:IJ B3:CD:EF:GH:IJ,
期望输出:
first|12:34:56:78:90|A0:CD:EF:GH:IJ,A1:CD:EF:GH:IJ,A2:CD:EF:GH:IJ,A3:CD:EF:GH:IJ second|98:76:54:32:10|B0:CD:EF:GH:IJ,B1:CD:EF:GH:IJ,B2:CD:EF:GH:IJ,B3:CD:EF:GH:IJ
解决方案
要实现客户端MAC地址用逗号分隔,需要在遍历wireless-network的基础上,嵌套遍历wireless-client节点,并处理最后一个客户端无需尾随逗号的情况。使用以下命令:
xmlstarlet sel -T -t \ -m '/detection-run/wireless-network' \ -v 'SSID/essid' -o "|" \ -v 'BSSID' -o "|" \ -m 'wireless-client' \ -v 'client-mac' \ -i 'position() != last()' -o "," \ -b \ -n xmll-02.kismet.netxml
命令说明:
-m '/detection-run/wireless-network':遍历每个无线网络节点- 先输出
essid和BSSID,用|分隔 -m 'wireless-client':嵌套遍历当前网络下的所有客户端节点-v 'client-mac':输出客户端MAC地址-i 'position() != last()' -o ",":仅当当前客户端不是最后一个时,输出逗号作为分隔符-b:结束内层的wireless-client遍历-n:每个网络信息后换行
执行该命令即可得到符合预期的输出格式。
内容的提问来源于stack exchange,提问作者Random Data Monster
相关产品推荐
相关产品推荐

