콜론으로 구분된 값 쌍을 구문 분석하고 필드에 이스케이프된 콜론 문자를 사용합니다.

콜론으로 구분된 값 쌍을 구문 분석하고 필드에 이스케이프된 콜론 문자를 사용합니다.

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가 필요합니다... 그냥 파이썬이라고 말하지 마세요...

답변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

관련 정보