解析冒号分隔的值对,并在字段中使用转义冒号字符

解析冒号分隔的值对,并在字段中使用转义冒号字符

我正在尝试处理 nmcli 命令的输出(冒号分隔值),但无法处理/忽略 MAC 或 BSSID 中的转义冒号。我尝试过 awk、jq、sed、正则表达式,但就是不明白......

管道命令:

nmcli -f SSID,BSSID,CHAN,FREQ,SIGNAL,SECURITY -t dev wifi

示例输出:

WiFi:00\:0A\:97\:6F\:7B\:AC:165:5660 MHz:15:

如果我将 BSSID 移动到行/字段列表的末尾(然后只剪切最后一个字段),它就会起作用,但现在这是一个值得骄傲的事情。请帮忙!

我确实找到了这个现有的 stackoverflow 线程,它确实做得很好,但我最终遇到了同样的问题,即如何忽略 MAC!@%$ 地址中的转义冒号: 解析冒号分隔的值对

最近的(可读的)尝试:

printf '%s' "$(nmcli -f SSID,BSSID,CHAN,FREQ,SIGNAL,SECURITY -t dev wifi)" | jq -sR 'split("\n") | map(split(":")) | map({"SSID": .[0], "BSSID": .[1], "CHAN": .[2], "RATE": .[3], "FREQ": .[4], "SIGNAL": .[5], "SECURITY": .[6]})'

和问题输出:

...
{
"SSID": "WiFi",
"BSSID": "00\\",
"CHAN": "0A\\",
"RATE": "97\\",
"FREQ": "6F\\",
"SIGNAL": "7B\\",
"SECURITY": "AC"
},
...

还需要 JQ 将冒号保留在适当的位置,而不是如上所示转义,如果可能的话,...请不要只说 python...

答案1

这里有一些注意事项:

  • 您可以nmcli通过以下方式防止转义字段--escape/-e no
  • 您不必引用 json 字段名称(不含特殊字符)
  • SSID并且Security并不总是返回,所以我添加了一个占位符 ( --)

    printf '%s' "$(nmcli -f SSID,BSSID,CHAN,FREQ,SIGNAL,SECURITY -e no -t dev wifi)" |
      jq -sR 'split("\n") |
        map(split(":") |
        {SSID: (if .[0] == "" then "--" else .[0] end), 
          BSSID: .[1:6] | join(":"),
          CHAN: .[7],
          FREQ: .[8],
          SIGNAL: .[9],
          SECURITY: (if .[10]  == "" then "--" else .[10] end)})'
    

答案2

Perl 允许您使用 Lookbehind 构造字段分隔符 - 并且还可以轻松地提供JSON模块。所以你可以做类似的事情

nmcli -f SSID,BSSID,CHAN,FREQ,SIGNAL,SECURITY -t dev wifi | 
  perl -F'(?<!\\):' -MJSON=encode_json -lne 'print encode_json([map { s/\\:/:/g ; $_ } @F])'

使用示例nmcli输出进行测试:

printf 'WiFi:00\:0A\:97\:6F\:7B\:AC:165:5660 MHz:15:' | 
  perl -F'(?<!\\):' -MJSON=encode_json -lne 'print encode_json([map { s/\\:/:/g ; $_ } @F])'
["WiFi","00:0A:97:6F:7B:AC","165","5660 MHz","15"]

答案3

用于sed清理数据,以及mlr将其转换为 JSON:

h='SSID,BSSID,CHAN,FREQ,SIGNAL,SECURITY'
nmcli -f $h -t dev wifi | 
sed 's/^:/"",/;s/\([^\]\):/\1,/g;s/[\]:/:/g' | 
mlr --c2j --jvstack  --jlistwrap  label $h

输出示例:

{
  "SSID": "FooBarBaz",
  "BSSID": "13:F6:8C:56:9B:3B",
  "CHAN": 36,
  "FREQ": "5180 MHz",
  "SIGNAL": 20,
  "SECURITY": "WPA1 WPA2"
},

答案4

GNU awk 可以将字段处理为转义字符或非冒号或反斜杠字符的序列(请参阅这个答案),所以以下应该有效。不是很有效,但至少是一个解决方案......

#!/bin/bash
line="WiFi:00\:0A\:97\:6F\:7B\:AC:165:5660 MHz:15:"
# line=`nmcli -f SSID,BSSID,CHAN,FREQ,SIGNAL,SECURITY -t dev wifi`
for i in 1 2 3 4 5; do
    echo $line | gawk -v FPAT='(\\\\.|[^\\\\:])*' '{print $'$i'}' 
done

相关内容