Bash 연관 배열을 jq 필터에 대한 인수로 전달합니다.

Bash 연관 배열을 jq 필터에 대한 인수로 전달합니다.

일부 위치 데이터로 작업 중이며 미국 우편 번호로 API를 쿼리하고 다음과 같은 결과를 반환합니다.

{ 
 "resultStatus":"SUCCESS",
  "zip5":"30301",
  "defaultCity":"ATLANTA",
  "defaultState":"GA",
  "defaultRecordType":"PO BOX",
  "citiesList":[],
  "nonAcceptList":[{"city":"ATL","state":"GA"}]
}

다음과 같이 전체 주 이름도 포함하는 출력을 생성하려면 이를 구문 분석해야 합니다. ATLANTA, Georgia, GA, 30301

나는 States라는 연관 배열을 만들어 ${States[GA]}값을 반환 Georgia하고 배열을 다음과 같은 인수로 jq에 전달하려고 했습니다.

curl -sS <enpoint> |jq -r '"${States[\(.defaultState)]}, \(.defaultState), \(.defaultCity), \(.zip5)"'

그 결과 출력이 발생했습니다.${States[GA]}, GA, ATLANTA, 30301

어쨌든 jq 필터 또는 이와 유사한 bash 배열을 전달하고 평가할 수 있습니까?

내가 보고 있는 유일한 옵션은 출력을 캡처하고 eval을 통과하는 것입니다. 물론 eval은 악합니다... 또한 이 작업을 수천 번 수행하고 파일의 다른 외부 데이터와 결합할 예정이므로 다음을 선호합니다. 내장된 bash 인수로 복잡한 문자열을 구성하고 평가하는 것보다 더 나은 옵션입니다.

편집하다

검색을 시도했다는 사실을 잊어버렸습니다.jq 1.6 매뉴얼운 좋게도 이것을 발견했습니다SO 포스트그래서 다음과 같이 States 배열을 jq arg로 전달하려고 했습니다.

curl -sS <enpoint> |jq -r --arg states $States '"$states[\(.defaultState)], \(.defaultState), \(.defaultCity), \(.zip5)"'

하지만 여전히 운이 없습니다.

steeldrivers 답변을 구현하는 실행 가능한 스크립트:

#! /bin/bash

# Do once and save
statesJson=$(for state in "${!StatesArray[@]}"; do 
                printf '{"name":"%s",\n"value":"%s"}\n' $state "${StatesArray[$state]}";
            done \
            | jq -s 'reduce .[] as $i ({}; .[$i.name] = $i.value)');

# Read zip and 6 other values from SourceDataFile.csv
while IFS=',' read -r zip fileValue02 fileValue03 fileValue04 fileValue05 fileValue06 fileValue07; do 

    # Use zip from file to get expanded location data.
    expandedLocationData=$(curl -sS '<apiEndpoint>' -H <Headers> --data "zip=$zip" |jq -r --argjson states "${statesJson}" '"\United States, US, ($states[.defaultState]), \(.defaultState), \(.defaultCity), \(.zip5)"');

    # Do useful things with the completed data set.
    echo "${expandedLocationData}, ${fileValue02} ${fileValue03}, ${fileValue04}, ${fileValue05}, ${fileValue06}, ${fileValue07}" > ./DestinationDataFile.csv

done < ./SourceDataFile.csv

답변1

bash 배열을 유효한 JSON 객체로 바꿀 수 있다면 (문자열 보간을 약간만 조정하여) --argjson. 예를 들어, 주어진

$ declare -p States
declare -A States=([GA]="Georgia" [NY]="New York" [ME]="Maine" )

그런 다음 언급

그 다음에

$ for k in "${!States[@]}"; do printf '{"name":"%s",\n"value":"%s"}\n' $k "${States[$k]}"; done | jq -s 'reduce .[] as $i ({}; .[$i.name] = $i.value)'
{
  "GA": "Georgia",
  "NY": "New York",
  "ME": "Maine"
}

~하도록 하다

$ jq -r --argjson states \
    "$(for k in "${!States[@]}"; do printf '{"name":"%s",\n"value":"%s"}\n' $k "${States[$k]}"; done | jq -s 'reduce .[] as $i ({}; .[$i.name] = $i.value)')" \
    '"\($states[.defaultState]), \(.defaultState), \(.defaultCity), \(.zip5)"' file.json
Georgia, GA, ATLANTA, 30301

관련 정보