最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

xml - How do I change the separator from a space to a comma with xmlstarlet? - Stack Overflow

programmeradmin3浏览0评论

I am parsing a file:

<?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>

I have the following formula to extract the essid, bssid and clients: 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.kismetxml)

However, that will list just one client for each network:

first|12:34:56:78:90|A0:CD:EF:GH:IJ,
second|98:76:54:32:10|B0:CD:EF:GH:IJ,

If I remove the concat portion, it will list all clients separated by a space:

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.kismetxml)
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

How do I get the clients with a comma as a delimiter? Desired output:

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

EDIT: I've also tried adding -o "," but that just adds a comma at the very end:

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,

I am parsing a file:

<?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>

I have the following formula to extract the essid, bssid and clients: 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.kismetxml)

However, that will list just one client for each network:

first|12:34:56:78:90|A0:CD:EF:GH:IJ,
second|98:76:54:32:10|B0:CD:EF:GH:IJ,

If I remove the concat portion, it will list all clients separated by a space:

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.kismetxml)
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

How do I get the clients with a comma as a delimiter? Desired output:

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

EDIT: I've also tried adding -o "," but that just adds a comma at the very end:

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,
Share Improve this question edited Mar 17 at 6:39 Ulrich Eckhardt 17.5k5 gold badges31 silver badges60 bronze badges asked Mar 14 at 3:35 Temp AccountTemp Account 3281 gold badge2 silver badges8 bronze badges 1
  • 1 concat combines all its arguments, doesn't join a node set; see developer.mozilla./en-US/docs/Web/XML/XPath/Reference/… – Shawn Commented Mar 14 at 4:11
Add a comment  | 

2 Answers 2

Reset to default 2

This is a bit tricky, as there doesn't seem to be a handy join function (concat just concatenates all its arguments together); you have to use nested for-each loops with multiple -m and -b (break) options, and a conditional to only add a comma after each but the last MAC address in the node set:

$ xmlstarlet sel -T -t -m /detection-run/wireless-network -v SSID/essid -o '|' -v BSSID -o '|' -m wireless-client -v client-mac --if 'not(position()=last())' -o , -b -b -nl input.xml
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

This should be also work:

-o "" → Ensure the last MAC doesn’t get an extra comma.
-n → Move to a new line for the next network.


xmlstarlet sel -T -t -m '/detection-run/wireless-network' \
-v 'SSID/essid' -o "|" \
-v 'BSSID' -o "|" \
-m 'wireless-client' -v 'client-mac' -o "," -b \
-o "" -n xmll-02.kismetxml

or with the string-join():


xmlstarlet sel -T -t -m '/detection-run/wireless-network' \ -v 'SSID/essid' -o "|" -v 'BSSID' -o "|" \ -v "string-join(wireless-client/client-mac, ',')" -n xmll-02.kismetxml
发布评论

评论列表(0)

  1. 暂无评论