コロンで区切られた値のペアを解析し、フィールドにエスケープされたコロン文字を使用します。

コロンで区切られた値のペアを解析し、フィールドにエスケープされたコロン文字を使用します。

nmcliコマンドの出力(コロンで区切られた値)を処理しようとしていますが、MACまたはBSSIDからエスケープされたコロンを処理/無視することはできません。 awk、jq、sed、regexを試しましたが、私は理解していません...

パイプラインコマンド:

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

出力例:

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

BSSIDを行/フィールドリストの最後に移動し、最後のフィールドだけを切り捨てるとうまくいきますが、今は誇りに思うでしょう。助けてください!

私は本当に良いことをしているこの既存のスタックオーバーフロースレッドを見つけましたが、最終的に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データクリーンアップのためmlrJSONに変換します。

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

関連情報