파이프라인 이후에 두 개의 연속 OP가 발생합니까, 아니면 한 번에 두 개의 jq OP가 발생합니까?

파이프라인 이후에 두 개의 연속 OP가 발생합니까, 아니면 한 번에 두 개의 jq OP가 발생합니까?

약간 변형된 JSON 문자열에서 데이터를 추출해야 하므로 먼저 sed& 를 통해 전달합니다 awk. 내가 가진 것은 다음 명령입니다.

`sed 's/},/},\n/g' test.json |awk '/"characater"/ { gsub("\"characater\"", "\"char" ++n "\"", $0) } 1'| jq -r '.frames.frame.lps.lp|.characters[]|[.code_ascii,.confidence]|@tsv'` 

다음과 같이 JSON 문자열에서 데이터를 추출합니다.

{"response":{"container":{"id":"41d6efcb-24d6-490d-8880-762255519b5f","timestamp":"2018-Jul-11 19:51:06.461665"},"id":"00000002-0000-0000-0000-000000000015"},"frames":{"frame":{"id":"5583","timestamp":"2016-Nov-30 13:05:27","lps":{"lp":{"licenseplate":"15451BBL","text":"15451BBL","wtext":"15451BBL","confidence":"20","bkcolor":"16777215","color":"16777215","type":"0","ntip":"11","cct_country_short":"","cct_state_short":"","tips":{"tip":{"poly":{"p":{"x":"1094","y":"643"},"p":{"x":"1099","y":"643"},"p":{"x":"1099","y":"667"},"p":{"x":"1094","y":"667"}},"bkcolor":"16777215","color":"0","code":"49","code_ascii":"1","confidence":"97"},"tip":{"poly":{"p":{"x":"1103","y":"642"},"p":{"x":"1113","y":"642"},"p":{"x":"1112","y":"667"},"p":{"x":"1102","y":"667"}},"bkcolor":"16777215","color":"0","code":"53","code_ascii":"5","confidence":"89"},"tip":{"poly":{"p":{"x":"1112","y":"640"},"p":{"x":"1122","y":"640"},"p":{"x":"1122","y":"666"},"p":{"x":"1112","y":"666"}},"bkcolor":"16777215","color":"0","code":"52","code_ascii":"4","confidence":"97"},"tip":{"poly":{"p":{"x":"1123","y":"640"},"p":{"x":"1132","y":"640"},"p":{"x":"1131","y":"665"},"p":{"x":"1123","y":"665"}},"bkcolor":"16777215","color":"0","code":"53","code_ascii":"5","confidence":"97"},"tip":{"poly":{"p":{"x":"1134","y":"640"},"p":{"x":"1139","y":"640"},"p":{"x":"1139","y":"664"},"p":{"x":"1133","y":"664"}},"bkcolor":"16777215","color":"0","code":"49","code_ascii":"1","confidence":"77"},"tip":{"poly":{"p":{"x":"1154","y":"639"},"p":{"x":"1163","y":"639"},"p":{"x":"1163","y":"663"},"p":{"x":"1153","y":"663"}},"bkcolor":"16777215","color":"0","code":"66","code_ascii":"B","confidence":"97"},"tip":{"poly":{"p":{"x":"1164","y":"638"},"p":{"x":"1173","y":"638"},"p":{"x":"1173","y":"663"},"p":{"x":"1163","y":"663"}},"bkcolor":"16777215","color":"0","code":"66","code_ascii":"B","confidence":"94"},"tip":{"poly":{"p":{"x":"1191","y":"637"},"p":{"x":"1206","y":"636"},"p":{"x":"1205","y":"660"},"p":{"x":"1190","y":"661"}},"bkcolor":"16777215","color":"0","code":"76","code_ascii":"L","confidence":"34"},"tip":{"poly":{"p":{"x":"1103","y":"655"},"p":{"x":"1111","y":"655"},"p":{"x":"1111","y":"667"},"p":{"x":"1103","y":"667"}},"bkcolor":"16777215","color":"0","code":"74","code_ascii":"J","confidence":"57"},"tip":{"poly":{"p":{"x":"1103","y":"655"},"p":{"x":"1111","y":"655"},"p":{"x":"1111","y":"667"},"p":{"x":"1103","y":"667"}},"bkcolor":"16777215","color":"0","code":"74","code_ascii":"J","confidence":"57"},"tip":{"poly":{"p":{"x":"1176","y":"638"},"p":{"x":"1185","y":"637"},"p":{"x":"1184","y":"661"},"p":{"x":"1175","y":"662"}},"bkcolor":"16777215","color":"0","code":"52","code_ascii":"4","confidence":"7"}},"ncharacter":"8","characters":{"characater":{"poly":{"p":{"x":"1094","y":"643"},"p":{"x":"1099","y":"643"},"p":{"x":"1099","y":"667"},"p":{"x":"1094","y":"667"}},"bkcolor":"16777215","color":"0","code":"49","code_ascii":"1","confidence":"97"},"characater":{"poly":{"p":{"x":"1103","y":"642"},"p":{"x":"1113","y":"642"},"p":{"x":"1112","y":"667"},"p":{"x":"1102","y":"667"}},"bkcolor":"16777215","color":"0","code":"53","code_ascii":"5","confidence":"89"},"characater":{"poly":{"p":{"x":"1112","y":"640"},"p":{"x":"1122","y":"640"},"p":{"x":"1122","y":"666"},"p":{"x":"1112","y":"666"}},"bkcolor":"16777215","color":"0","code":"52","code_ascii":"4","confidence":"97"},"characater":{"poly":{"p":{"x":"1123","y":"640"},"p":{"x":"1132","y":"640"},"p":{"x":"1131","y":"665"},"p":{"x":"1123","y":"665"}},"bkcolor":"16777215","color":"0","code":"53","code_ascii":"5","confidence":"97"},"characater":{"poly":{"p":{"x":"1134","y":"640"},"p":{"x":"1139","y":"640"},"p":{"x":"1139","y":"664"},"p":{"x":"1133","y":"664"}},"bkcolor":"16777215","color":"0","code":"49","code_ascii":"1","confidence":"77"},"characater":{"poly":{"p":{"x":"1154","y":"639"},"p":{"x":"1163","y":"639"},"p":{"x":"1163","y":"663"},"p":{"x":"1153","y":"663"}},"bkcolor":"16777215","color":"0","code":"66","code_ascii":"B","confidence":"97"},"characater":{"poly":{"p":{"x":"1164","y":"638"},"p":{"x":"1173","y":"638"},"p":{"x":"1173","y":"663"},"p":{"x":"1163","y":"663"}},"bkcolor":"16777215","color":"0","code":"66","code_ascii":"B","confidence":"94"},"characater":{"poly":{"p":{"x":"1191","y":"637"},"p":{"x":"1206","y":"636"},"p":{"x":"1205","y":"660"},"p":{"x":"1190","y":"661"}},"bkcolor":"16777215","color":"0","code":"76","code_ascii":"L","confidence":"34"}},"det_time_us":"1072592","poly":{"p":{"x":"1088","y":"642"},"p":{"x":"1210","y":"634"},"p":{"x":"1210","y":"661"},"p":{"x":"1087","y":"669"}}}},"det_time_us":"1720812"}}}

또는 다음 링크에서:https://drive.google.com/file/d/18wCzjMBpw7SIeVFByAGPQiqCBjg_0te3/view?usp=sharing
이제 이것은 훌륭하게 작동하지만 .frames.frame.lps.lp.ncharacterJSON에서도 추출해야 합니다. 위와 같은 작업을 간단히 수행할 수 있다는 것을 알고 있지만 문자열로 구성된 거대한 JSON 파일을 구문 분석하려면 이러한 명령이 필요하고 문자열은 링크에 표시된 형식이며 매개변수가 표시되어야 cat test.json | jq -r '.frames.frame.lps.lp.ncharacter';하기 때문에 작동하지 않습니다. .ncharacter추출된 문자가 있는 줄은 다음과 유사한 출력을 원한다는 것을 의미합니다.

...
X       99
Y       99 previous data formatted in the same way
8
1       97
5       89
4       97
5       97
1       77
B       97
B       94
L       34
6          following data formatted in the same way
Z       99
...

상위 8개는 .ncharacter매개변수입니다. 나는 시도했다:

sed 's/},/},\n/g' test.json |awk '/"characater"/ { gsub("\"characater\"", "\"char" ++n "\"", $0) } 1'| jq -r '[.frames.frame.lps.lp.ncharacter],.frames.frame.lps.lp|.characters[]|[.code_ascii,.confidence]|@tsv'

하지만 이것이 나에게 주는 jq: error (at <stdin>:102): Cannot index array with string "characters"이유는 모르겠습니다...

답변1

확인하다:

첫 번째 변종

perl -pe 's/"characater"/"\"char" . (++$n) . "\""/ge' input.json |
jq -r '.frames.frame.lps.lp|.ncharacter,(.characters[]|[.code_ascii,.confidence]|@tsv)'

설명하다

  1. perl -pe 's/"characater"/"\"char" . (++$n) . "\""/ge' input.json

    • -p- 각 줄을 반복하고 다음과 같이 인쇄합니다 sed.
    • -e- 한 줄 프로그램을 입력하는 데 사용할 수 있습니다. 주어 지면 -ePerl은 인수 목록에서 파일 이름을 찾지 않습니다.
    • s///ge- g: 전역 교체, e: 교체 명령의 오른쪽 부분을 표현식으로 평가합니다.
    • "\"char" . (++$n) . "\""- 포인트는 연결에 사용됩니다.
  2. jq -r '.frames.frame.lps.lp|.ncharacter,(.characters[]|[.code_ascii,.confidence]|@tsv)'

    • .frames.frame.lps.lp|- 로 작성할 수 있으므로 .frames | .frame | .lps | .lp |다음과 같이 작동합니다. 입력을 받고 모든 frames필드를 선택하여 다른 필터로 파이프한 .frame다음 모든 frame필드를 가져와 다음 필터로 파이프하는 등 - .lps등이 계속됩니다. 바라보다jq 매뉴얼, 이것관로부분.
    • |.ncharacter,(.characters[]|...)'-jq 매뉴얼, 이것반점부분: "두 개의 필터가 쉼표로 구분된 경우 동일한 입력이 두 필터 모두에 공급되고 두 필터의 출력 값 스트림이 순서대로 연결됩니다. 먼저 왼쪽 표현식에 의해 생성된 모든 출력, 그런 다음 모두 예를 들어 필터는 .foo, .bar"foo" 필드와 "bar" 필드를 별도의 출력으로 생성합니다.
    • (.characters[]|[.code_ascii,.confidence]|@tsv).characters[]- 괄호는 필터 출력과 별도로 처리되는 출력 에 사용됩니다 .ncharacter.

두 번째 변형- gawk대신 perl파일 json수정을 사용하세요. 이 jq부분은 첫 번째 변형과 동일합니다.

gawk '{ORS= (RT) ? "\"char" NR "\"" : ""; print}' RS='"characater"' input.json

노트- perl그리고 명령은 매 프레임마다 블록의 카운터를 재설정 gawk하지 않습니다 . char즉, 처음부터 시작 char1하여 끝까지 증가합니다.

입력하다- 샘플이 3번 복제되었습니다.

산출

8
1   97
5   89
4   97
5   97
1   77
B   97
B   94
L   34
8
1   97
5   89
4   97
5   97
1   77
B   97
B   94
L   34
8
1   97
5   89
4   97
5   97
1   77
B   97
B   94
L   34

답변2

이것은 동일한 주제에 대한 또 다른 질문의 연속입니다. 여기서 주요 문제는 입력에 고유하지 않은 키가 있는 객체가 포함되어 있다는 것입니다. 이는 여전히 유효한 JSON이지만 이후 키가 이전 키를 덮어쓰므로 문서를 구문 분석할 때 데이터가 "손실"됩니다.

이전 질문에 여기에 답변했습니다., 답변에 설명된 다음 명령을 사용하십시오.

$ jq -r -n --stream 'fromstream(1|truncate_stream(5|truncate_stream(inputs)|select(.[0][0] == "characater"))) | [.code_ascii, .confidence] | @tsv' test.json
1       97
5       89
4       97
5       97
1       77
B       97
B       94
L       34

문제는이것문제는 출력이 출력 라인 수 앞에 자체 라인에 있어야 한다는 것입니다. 이러한 이상한 형식의 JSON 문서는 단 하나의 인스턴스가 아니라 전체 세트가 한 줄에 하나씩 있습니다.

다음은 결과를 배열로 수집하여 출력하기 전에 요소 수를 계산하는 위 명령을 수정한 것입니다.

$ jq -r -n --stream '[fromstream(1|truncate_stream(5|truncate_stream(inputs)|select(.[0][0] == "characater"))) | [.code_ascii, .confidence]] | length, (.[]|@tsv)' test.json
8
1       97
5       89
4       97
5       97
1       77
B       97
B       94
L       34

그런 다음 원본 파일의 각 줄에 대해 이 명령을 한 번씩 호출하면 됩니다.

#!/bin/bash

cmd=( jq -r -n --stream '[fromstream(1|truncate_stream(5|truncate_stream(inputs)|select(.[0][0] == "characater"))) | [.code_ascii, .confidence]] | length, (.[]|@tsv)' )

while IFS= read -r json; do
    printf '%s\n' "$json" | "${cmd[@]}"
done <test.json

관련 정보