텍스트 파일을 JSON으로 변환

텍스트 파일을 JSON으로 변환

컬을 사용하여 TP-Link 라우터에서 일부 통계를 얻고 있습니다. 해당 정보를 텍스트 파일에 넣었습니다. 하지만 이 정보를 다른 곳에서 사용할 수 있으려면 JSON 형식이 필요합니다. 텍스트 파일의 형식은 다음과 같습니다.

[0,0,0,0,0,0]0
enable=1
interval=10
action=0
[1,0,0,0,0,0]1
ipAddress=3232235848
macAddress=EC:0E:C4:4F:XX:XX
totalPkts=201
totalBytes=22914
currPkts=0
currBytes=0
currIcmp=0
currUdp=0
currSyn=0
currIcmpMax=0
currUdpMax=15
currSynMax=0
[2,0,0,0,0,0]1
ipAddress=3232235829
macAddress=00:16:E8:22:XX:XX
totalPkts=972
totalBytes=98730
currPkts=0
currBytes=0
currIcmp=0
currUdp=0
currSyn=0
currIcmpMax=0
currUdpMax=14
currSynMax=4
[3,0,0,0,0,0]1
ipAddress=3232235842
macAddress=70:14:A6:8B:XX:XX
totalPkts=154566
totalBytes=15116490
currPkts=0
currBytes=0
currIcmp=0
currUdp=0
currSyn=0
currIcmpMax=9
currUdpMax=58
currSynMax=60

다음과 같은 JSON이 필요합니다.

{"ipAddress" : "3232235848",
"macAddress" : "EC:0E:C4:4F:XX:XX",
"totalPkts" : "201",
"totalBytes" : "22914",
"currPkts" : "0",
"currBytes" : "0",
"currIcmp" : "0",
"currUdp" : "0",
"currSyn" : "0",
"currIcmpMax" : "0",
"currUdpMax" : "15",
"currSynMax" : "0"}
{"ipAddress" : "3232235829", ...

가장 효율적인 방법을 알려주실 수 있나요? 가능하다면 bash 스크립트를 선호합니까? 컬 명령 끝에 "| jq -R -s -c 'split("\n")'"을 넣으려고 했지만 다음과 같습니다: {"ipAddress=3232235848","macAddress=EC:0E:C4: 4F: XX:XX”...

답변1

sed금이 가다:

sed -E -e 's/\[([0-9],){5}[0-9]\][0-9]+/}{/g; s/([[:alnum:]]+)=([[:alnum:]]+)/"\1" : "\2",/; 
           s/,\n}/}/;  1s/.*/{/; $s/.*/&}/' yourfile | sed -Ez 's/,\n?}/ }\n/g'

산출:

{
"enable" : "1",
"interval" : "10",
"action" : "0" }
{
"ipAddress" : "3232235848",
"macAddress" : "EC",:0E:C4:4F:XX:XX
"totalPkts" : "201",
"totalBytes" : "22914",
"currPkts" : "0",
"currBytes" : "0",
"currIcmp" : "0",
"currUdp" : "0",
"currSyn" : "0",
"currIcmpMax" : "0",
"currUdpMax" : "15",
"currSynMax" : "0" }
{
"ipAddress" : "3232235829",
"macAddress" : "00",:16:E8:22:XX:XX
"totalPkts" : "972",
"totalBytes" : "98730",
"currPkts" : "0",
"currBytes" : "0",
"currIcmp" : "0",
"currUdp" : "0",
"currSyn" : "0",
"currIcmpMax" : "0",
"currUdpMax" : "14",
"currSynMax" : "4" }
{
"ipAddress" : "3232235842",
"macAddress" : "70",:14:A6:8B:XX:XX
"totalPkts" : "154566",
"totalBytes" : "15116490",
"currPkts" : "0",
"currBytes" : "0",
"currIcmp" : "0",
"currUdp" : "0",
"currSyn" : "0",
"currIcmpMax" : "9",
"currUdpMax" : "58",
"currSynMax" : "60" }

답변2

perl -lne 'BEGIN{*1 = sub {print q<{>, join(",\n", splice @A, 0, @A), q<}>}}
   next if $. == 1;
   /^\[(?:\d+,?)+\]\d+$/ and &1,next;
   push @A, join q/ : /, map qq/"$_"/, split /=/;
   eof && &1;
' yourfile

답변3

사용밀러( mlr) 몇 가지 간단한 전처리 후 sed:

sed 's/^\[.*//' file | mlr --irs lflf --ifs lf --ojson cat

이것은 먼저 sed로 시작하는 줄을 지우는 데 사용됩니다 [. 생성된 빈 줄은 Miller의 레코드 구분 기호 역할을 합니다.

그런 다음 Miller는 데이터를 추가로 수정하지 않고 입력을 JSON으로 변환합니다. Miller가 데이터를 이해할 수 있도록 입력 레코드 구분 기호는 이중 개행 문자이고 입력 필드 구분 기호는 단일 개행 문자임을 지정합니다.

질문의 샘플 데이터를 고려하면 이 명령은 다음과 같은 출력을 생성합니다.

[
{
  "enable": 1,
  "interval": 10,
  "action": 0
},
{
  "ipAddress": 3232235848,
  "macAddress": "EC:0E:C4:4F:XX:XX",
  "totalPkts": 201,
  "totalBytes": 22914,
  "currPkts": 0,
  "currBytes": 0,
  "currIcmp": 0,
  "currUdp": 0,
  "currSyn": 0,
  "currIcmpMax": 0,
  "currUdpMax": 15,
  "currSynMax": 0
},
{
  "ipAddress": 3232235829,
  "macAddress": "00:16:E8:22:XX:XX",
  "totalPkts": 972,
  "totalBytes": 98730,
  "currPkts": 0,
  "currBytes": 0,
  "currIcmp": 0,
  "currUdp": 0,
  "currSyn": 0,
  "currIcmpMax": 0,
  "currUdpMax": 14,
  "currSynMax": 4
},
{
  "ipAddress": 3232235842,
  "macAddress": "70:14:A6:8B:XX:XX",
  "totalPkts": 154566,
  "totalBytes": 15116490,
  "currPkts": 0,
  "currBytes": 0,
  "currIcmp": 0,
  "currUdp": 0,
  "currSyn": 0,
  "currIcmpMax": 9,
  "currUdpMax": 58,
  "currSynMax": 60
}
]

결과 배열의 첫 번째 개체를 방지하려면 첫 번째 레코드 출력을 방지하는 작업 cat으로 작업을 변경하세요 .filter

sed 's/^\[.*//' file | mlr --irs lflf --ifs lf --ojson filter 'NR > 1'

아직도 하시겠습니까?아니요결과 JSON 객체를 배열로 래핑하고 Miller를 사용합니다 --no-jlistwrap.

sed 's/^\[.*//' file | mlr --irs lflf --ifs lf --ojson --no-jlistwrap filter 'NR > 1'

--ojson...또는 다음으로 변경하여 행당 하나의 객체 JSON 출력 형식으로 변경합니다 --ojsonl.

sed 's/^\[.*//' file | mlr --irs lflf --ifs lf --ojsonl filter 'NR > 1'

...결과는

{"ipAddress": 3232235848, "macAddress": "EC:0E:C4:4F:XX:XX", "totalPkts": 201, "totalBytes": 22914, "currPkts": 0, "currBytes": 0, "currIcmp": 0, "currUdp": 0, "currSyn": 0, "currIcmpMax": 0, "currUdpMax": 15, "currSynMax": 0}
{"ipAddress": 3232235829, "macAddress": "00:16:E8:22:XX:XX", "totalPkts": 972, "totalBytes": 98730, "currPkts": 0, "currBytes": 0, "currIcmp": 0, "currUdp": 0, "currSyn": 0, "currIcmpMax": 0, "currUdpMax": 14, "currSynMax": 4}
{"ipAddress": 3232235842, "macAddress": "70:14:A6:8B:XX:XX", "totalPkts": 154566, "totalBytes": 15116490, "currPkts": 0, "currBytes": 0, "currIcmp": 0, "currUdp": 0, "currSyn": 0, "currIcmpMax": 9, "currUdpMax": 58, "currSynMax": 60}

관련 정보