Bash를 사용하면 파일 목록을 나타내는 인덱스 배열이 있습니다.
a=("1.json" "2.json" "3.json" ... "5309.json")
이 JSON 파일의 두 데이터 필드를 두 개의 연관 배열로 구문 분석합니다.
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
한 번에 하나의 파일을 반복하기 때문에 모든 파일을 처리하는 데 꽤 시간이 걸립니다. 루프 내에서 생성된 연관 배열은 루프가 완료된 후에도 계속해서 범위를 초과해야 한다는 요구 사항이 있습니다.
parallel
여러 배열 항목을 동시에 처리하면서도 연관 배열에 데이터를 제공할 수 있는 방법(예: 처리 또는 기타 방법 사용)이 있습니까 ?
답변1
여기에서 속도가 느릴 수 있는 점은 jq
파일당 두 개의 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
./-