You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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以逗号分隔。尝试了几种命令都没得到预期结果:

  1. 使用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,
  1. 移除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
  1. 添加-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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:24:51