Bash
將 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 Post導致我嘗試將 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
如果您可以將 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