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[GA]}値を返すためにStatesという名前の連想配列を作成し、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 マニュアル運がないですね。これを見つけました。だから郵便でこれにより、次のようにStates配列をjq引数として渡そうとしました。

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

おすすめ記事