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

関連情報