콜론으로 구분된 값 쌍(nmcli 출력)을 구문 분석하고 다음에서 JSON으로 변환합니다.

콜론으로 구분된 값 쌍(nmcli 출력)을 구문 분석하고 다음에서 JSON으로 변환합니다.

나는 썼다스크립트출력을 nmcli --mode multiline dev wifiJSON으로 변환했지만 일관성이 없습니다.(결과에 공백이 있으면 중단됨), 길고 읽기 어렵습니다.

결과를 직접 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"
  }
]

관련 정보