Bash - 파일을 반복하고 마스터 키 파일의 해당 키에서 JSON 값을 추출합니다.

Bash - 파일을 반복하고 마스터 키 파일의 해당 키에서 JSON 값을 추출합니다.

파일 목록이 포함된 파일을 반복하는 bash 스크립트를 만들려고 합니다(그래서 각 파일을 반복합니다). 파일이 열리면 다른 프로그램(jq)을 사용하여 JSON 파일의 키-값 쌍에서 값을 추출하고 싶습니다. 지금까지 제가 작업하고 있는 작업은 다음과 같습니다. 매우 기본적인 작업을 유지하여 무엇이 잘못되었는지 알아내려고 노력할 수 있습니다. jq 명령은 신경 쓰지 않습니다. 작동하고 있습니다. 모든 파일을 반복하여 단일 키의 값을 추출할 수 있지만 각 키에 대해 수동으로 변경해야 하므로 결국 매우 지루해집니다. .

간단히 말해서: "마스터"는 열려는 각 JSON 파일의 전체 경로가 포함된 파일입니다. "key.txt"는 이러한 JSON 파일에서 가능한 모든 키를 포함하는 파일입니다. $KEY는 열린 파일에서 해당 특정 키를 검색하고 해당 키의 값을 반환하는 jq의 구문입니다. 기본 목록에 있는 파일을 열고, 가능한 모든 키를 반복하고, 해당 키의 값을 "list.txt"라는 텍스트 파일로 반환하고 싶습니다.

어떤 도움이라도 대단히 감사하겠습니다.

#!/bin/bash

master="path/masterlist.txt"
while read master
do
        for KEY in 'key.txt'
        do
                jq '. .'$KEY'' $f
                echo $KEY
        done >> list.txt
        echo $master
done < list.txt

답변1

이것은 더 많은 경험을 얻었으므로 지금 다시 방문하는 오래된 답변입니다 jq.

문제의 사용자는 이렇게 말했습니다.

나는 jq 명령에 관심이 없습니다 [...]

...하지만 실제로 jq이 작업을 효율적으로 수행하려면 명령이 핵심입니다.

요약하자면, 사용자는 텍스트 파일 .txt에 나열된 모든 키에 대한 모든 값을 추출하려고 합니다 keys.txt. 그들은 다른 파일 .txt에 나열된 모든 JSON 파일에 대해 이 작업을 수행하려고 합니다 list.txt.

, , 를 사용하여 파일 세트 , , a키 세트 b의 모든 (디코딩된) 값을 얻으려면 다음을 수행할 수 있습니다.cfile1file2file3jq

jq -r '.[$ARGS.positional[]] // empty' file1 file2 file3 --args a b c

이는 키로 사용된 문자열을 에 전달하고 jq, 에서는 이를 배열의 요소로 받아들입니다 $ARGS.positional. 배열이 확장되고 해당 요소는 입력에서 값을 얻기 위한 키로 사용됩니다. 여기서는 empty키 값이 존재하지 않거나 이면 아무것도 반환하지 않기로 선택했습니다 null.

파일 목록과 키 목록이 모두 임의로 길 수 있고 두 파일 모두 필요에 따라 인용된 줄을 포함한다고 가정하고 이 작업의 핵심 주위에 셸 파이프를 추가합니다.

xargs sh -c '
    xargs jq -r ".[\$ARGS.positional[]] // empty" "$@" --args <keys.txt
' sh <list.txt >result.txt

파일 이름 목록을 가져오고 짧은 인라인 쉘 스크립트를 호출하여 파일을 일괄 처리합니다. 인라인 스크립트는 주어진 파일 이름()과 키 목록에서 읽은 키 세트로 xargs호출됩니다 .jq"$@"

결과 값 목록이 작성됩니다 result.txt.


이전 답변은 다음과 같습니다.

당신이 하고 싶다고 말한 것을 읽은 후:

master="path/masterlist.txt"

while read json_path; do
    while read key; do
        printf 'File="%s", Key="%s"\n' "$json_path" "$key"
        jq ". .'$key'" "$json_path"
    done <key.txt
done <"$master" >list.txt

JSON 파일 목록을 읽고 $master각 경로를 차례로 할당합니다.json_path

key.txt내부 루프에서는 키를 순차적으로 읽고 할당합니다 key. 유틸리티는 jq현재 키 값으로 확장된 인수를 사용하여 호출됩니다.$json_path. .'$key'$key

모든 출력은 에 입력됩니다 list.txt.

내부 루프에는 약간의 최적화가 필요할 수 있습니다. 예를 들어 외부 루프를 반복할 때마다 모든 키를 읽을 필요는 없는 것 같습니다.


주석이 달린 스크립트 버전:

master="path/masterlist.txt"        # this is never used
while read master                   # this will set $master to something from list.txt
do
        for KEY in 'key.txt'        # $KEY will be the string 'key.txt' (nothing else)
        do
                jq '. .'$KEY'' $f   # $f is empty
                echo $KEY
        done >> list.txt            # better to >list.txt after "done" of outer loop
        echo $master
done < list.txt                     # you probably don't want to read from this file

답변2

$f올려주신 스크립트를 읽어보니 할당이 잘못된 것 같습니다 . 또한 명령 내의 참조로 jq인해 문제가 발생할 수 있습니다. 실제로 while 루프에서 단어를 읽으려고 시도하고 있으며 루프 내부에 단어를 추가하려고 master시도 할 수도 있습니다.list.txtlist.txt

#!/bin/bash

master="path/masterlist.txt"

cat $master | while read f; do
    for KEY in 'key.txt'; do
        echo $(jq ". .'$KEY'" $f) >> list.txt
    done
    echo $master
done

그러면 파일에서 각 줄을 가져와 $master루프의 변수에 할당한 다음 쿼리를 실행하고 출력을 .$fjqlist.txt

관련 정보