Bashでは、ファイルのリストを表すインデックス配列があります。
a=("1.json" "2.json" "3.json" ... "5309.json")
このJSONファイルの2つのデータフィールドを2つの連想配列に解析します。
declare -A idArr
declare -A valueArr
for i in "${a[@]}"; do
jqId="$(jq -M ".fileId" <"${i}")"
jqValue="$(jq -M ".value" <"${i}")"
# If there are already items in the associative array, add the new items separated by a newline
idArr[${i}]="${idArr[${i}]}${idArr[${i}]:+$'\n'}${jqId}"
valueArr[${jqId}]="${valueArr[${jqId}]}${valueArr[${jqId}]:+$'\n'}${jqValue}"
done
一度に1つのファイルを繰り返すので、すべてのファイルを処理するのにかなり時間がかかります。ループ内で生成された連想配列は、ループが完了した後も引き続き範囲を超えなければならないという要件があります。
parallel
複数の配列項目を同時に処理しながら、連想配列にデータを提供する方法(処理または他の方法を使用)はありますか?
ベストアンサー1
ここで遅いことができるのは、jq
ファイルごとに2つのsを実行し、プロセスをフォークしてjq
その中で実行することが、おそらく小さなjsonファイルを処理するよりもはるかに多くの作業量です。
read0() { IFS= read -rd '' "$@"; }
add_line() {
typeset -n _var="$1"
_var+=${_var:+$'\n'}$2
}
shopt -s extglob failglob lastpipe
set -o pipefail
typeset -A idArr valueArr
jq -j '[input_filename, .fileId, .value] |
map(gsub("\u0000"; "") + "\u0000") | add
' -- +([0123456789]).json |
while read0 file && read0 id && read0 value; do
add_line "idArr[$file]" "$id"
add_line "valueArr[$file]" "$var"
done
一度だけ実行されますjq
。jq
bashがループから並列に読み取るとき、NULで区切ってファイル名、ID、および値(存在する場合はNULを削除)を印刷します。
重要なヒント:するいいえわずかに偽装されているadd_line
ため、コマンドインジェクションの脆弱性になる可能性があるため、任意のファイル名で呼び出してください。たとえば、代わりにを使用し、というファイルがある場合、再起動します!typeset -n
eval
*.json
+([0123456789]).json
$(reboot).json
現在のバージョンのbashでは、二重引用符の代わりに一重引用符を使用してこの問題を解決できますが、idArr[$file]
将来valueArr[$file]
のバージョンのbashでは、namerefの逆参照に対してこれらの拡張を実行しないことを決定できるため、これは将来の証拠ではない可能性があります。
または、誤って設計された名前参照を削除し、eval
それらを明示的に使用してこれらの脆弱性を排除する可能性があります。
add_line() {
eval "$1+=\${$1:+\$'\\n'}\$2"
}
そして必ず次のように呼び出してください。
add_line 'idArr[$file]' "$id"
add_line 'valueArr[$file]' "$var"
その後、消毒を使用*.json
したり、必要としないことがあります。"${a[@]}"
「パラメータのリストが長すぎます。」エラーが発生した場合jq ... +([0123456789]).json
にに置き換えてくださいprintf '%s\0' +([0123456789]).json | xargs -r0 jq ...
。
xargs
GNU 'を使用して-P
それらのいくつかを並列に実行することもできますが、コマンド出力のシリアル化は保証されておらず、個々のsの出力が互いに絡み合う可能性があるため、お勧めできjq
ません。 GNUはそうです。しかし、(おそらく)短いJSONファイルを解析するなどの単純な操作に比べてオーバーヘッドが多いため、追加の利点がない可能性があります。xargs
jq
parallel
1は標準入力jq
として扱われるので、-
厳密に言うと、そのような名前のファイルが配列(または代わりに$a
glob拡張子)に存在する場合はこれを。*
*.json
./-