
私は書いたスクリプト出力を
nmcli --mode multiline dev wifi
JSONに変換しましたが、一貫性がありません。(結果にスペースがある場合は中断されます)、長くて読みにくいです。
結果を直接jq
。
出力nmcli
(私のスクリプトへの入力)は次のとおりです。
*:
SSID: VIDEOTRON2255
MODE: Infra
CHAN: 11
RATE: 54 Mbit/s
SIGNAL: 69
BARS: ▂▄▆_
SECURITY: WPA1 WPA2
*: *
SSID: VIDEOTRON2947
MODE: Infra
CHAN: 6
RATE: 54 Mbit/s
SIGNAL: 49
BARS: ▂▄__
SECURITY: WPA1 WPA2
次のようなものを作成したいと思います。
[{
"network": "VIDEOTRON2255",
"mode": "Infra",
"chan": "11",
"rate": "54 Mbit/s",
"signal": "69",
"bars": "▂▄▆_",
"security": "WPA1 WPA2"
},
{
"network": "VIDEOTRON2947",
"mode": "Infra",
"chan": "6",
"rate": "54 Mbit/s",
"signal": "49",
"bars": "▂▄__",
"security": "WPA1 WPA2"
}]
私は尋ねた関連質問より早く。これは最初のスクリプト元に書きました。ザイルズの答え。一部の値では機能しますが、security
スペースでは機能しませんrate
。
答え1
あなたがリンクしたスクリプトは非常に非効率的です。使用されているモードで…役に立たない前処理をたくさんしています。
なぜならマニュアルによると、nmcli
--terse
「このモードはコンピュータ(スクリプト)処理用に設計されています。」、必須フィールドを指定し、出力をたとえばjq -sR
パイプします。
printf '%s' "$(nmcli -f ssid,mode,chan,rate,signal,bars,security -t dev wifi)" | \
jq -sR 'split("\n") | map(split(":")) | map({"network": .[0],
"mode": .[1],
"channel": .[2],
"rate": .[3],
"signal": .[4],
"bars": .[5],
"security": .[6]})'
答え2
これ牛に似た一種の栄養 sed
コードではありませんがjq
(複雑な変換ではありません)、十分にうまくいくようです。バー出てきたら大丈夫でしょう):
nmcli --mode multiline dev wifi |
sed '/^*/! {s/^[A-Z]*/\L&/
s/ssid/network/
s/: */": "/
s/$/"/
{/^sec/!s/$/,/}
s/^/\t"/}
1 s/^\*.*/[{/
/^\*/ s/.*/},\n{/
$ {p;s/.*/}]/}'
スタンドアロンスクリプトを読みやすくしますpcsvp.sed
(ファイルに保存して実行chmod +x pcsvp.sed
)。
#!/bin/sed -f
# Text lines (the non "*:" lines.)
/^*/! {s/^[A-Z]*/\L&/
s/ssid/network/
s/: */": "/
s/$/"/
{/^sec/!s/$/,/}
s/^/\t"/}
# First JSON line
1 s/^\*.*/[{/
# Middle JSON lines. If a line begins with a '*'...
/^\*/ s/.*/},\n{/
# Last line, close up the JSON.
$ {p;s/.*/}]/}
実行するには、次のようにします。
nmcli --mode multiline dev wifi | ./pcsvp.sed
注:入力ファイルに関する質問、代わりに入力を使用することにしましたnmcli
。私の場所では約50のネットワークが表示されているため、ここで引用するには結果の出力が長すぎます。
入力サンプルのスペルエラーが修正されると、./pcsvp.sed input.txt
出力は次のようになります。
[{
"network": "VIDEOTRON2255",
"mode": "Infra",
"chan": "11",
"rate": "54 Mbit/s",
"signal": "69",
"bars": "▂▄▆_",
"security": "WPA1 WPA2"
},
{
"network": "VIDEOTRON2947",
"mode": "Infra",
"chan": "6",
"rate": "54 Mbit/s",
"signal": "49",
"bars": "▂▄__",
"security": "WEP"
}]
答え3
複雑jq
解決策(BARS
不規則/非ASCII文字が含まれているため、行を削除してください):
入力ファイルinput.txt
:
*:
SSID: VIDEOTRON2255
MODE: Infra
CHAN: 11
RATE: 54 Mbit/s
SIGNAL: 69
SECURITY: WPA1 WPA2
*: *
SSID: VIDEOTRON2947
MODE: Infra
CHAN: 6
RATE: 54 Mbit/s
SIGNAL: 49
SECURITY: WPA1 WPA2
働く:
jq -sR '[ gsub("[*]: *\n| {2,}";"") | gsub("SSID";"network") | split("\n[*]:[*] +\n";"n")[]
| [ capture("(?<key>[^:\n]+):(?<value>[^:\n]+)";"g") | .key |= (. | ascii_downcase) ]
| from_entries ]' input.txt
出力:
[
{
"network": "VIDEOTRON2255",
"mode": "Infra",
"chan": "11",
"rate": "54 Mbit/s",
"signal": "69",
"security": "WPA1 WPA2"
},
{
"network": "VIDEOTRON2947",
"mode": "Infra",
"chan": "6",
"rate": "54 Mbit/s",
"signal": "49",
"security": "WPA1 WPA2"
}
]
他の特定の入力を投稿または投稿する追加の方法https://pastebin.com/8stHSUeu:
jq -sR '[sub("[*]: *[*]\n";"") | gsub(" {2,}";"") | gsub("SSID";"network")
| split("\n[*]: *\n";"n")[]
| [ capture("(?<key>[^:\n]+):(?<value>[^:\n]+)";"g") | .key |= (. | ascii_downcase) ]
| from_entries]' input.txt
答え4
可能であれば、JSONを前後に理解するツールを使用してください。私はPythonを使用します。
#! /usr/bin/env python3
import json
import re
import sys
objects = []
obj = {}
for line in sys.stdin:
entry = re.split(':\s*', line.strip(), maxsplit=1) # split on first `:`
if entry[0] == '*':
if obj: # skip a null entry (the first, here)
obj['network'] = obj.pop('ssid') # rename the SSID entry
objects.append(obj)
obj = {} # start a new object for each `*`
continue
obj[entry[0].lower()] = entry[1] # lowercase the key
obj['network'] = obj.pop('ssid') # rename the SSID entry
objects.append(obj)
json.dump(objects, sys.stdout)
ご理解ください:
[{"mode": "Infra", "chan": "11", "rate": "54 Mbit/s", "signal": "69", "bars": "\u2582\u2584\u2586_", "security": "WPA1 WPA2", "network": "VIDEOTRON2255"}, {"ssid": "VIDEOTRON2947", "mode": "Infra", "chan": "6", "rate": "54 Mbit/s", "signal": "49", "bars": "\u2582\u2584__", "security": "WPA1 WPA2"}]
美しく印刷するとjq
次のようになります。
[
{
"mode": "Infra",
"chan": "11",
"rate": "54 Mbit/s",
"signal": "69",
"bars": "▂▄▆_",
"security": "WPA1 WPA2",
"network": "VIDEOTRON2255"
},
{
"ssid": "VIDEOTRON2947",
"mode": "Infra",
"chan": "6",
"rate": "54 Mbit/s",
"signal": "49",
"bars": "▂▄__",
"security": "WPA1 WPA2"
}
]