将 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 手册没有运气,发现了这个所以邮政这导致我尝试将 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

相关内容