json 字典到 bash 散列 table 使用 readarray
json dictionary to bash hash table using readarray
首先是数组的工作示例
json_array() {
local -n array=""
readarray -d $'[=13=]' -t array < <(
# Create nul delimited array entry using jq
jq -cjn --argjson arr "$array" '$arr|map(tostring)|.[]+"\u0000"'
)
}
> unset arr; arr='["a", "b", "c"]'; json_array arr; echo "${arr[0]} ${arr[1]} ${arr[2]}"
a b c
现在我正在尝试用 dict 做一些类似的事情,将 json dict 转换成 bash 关联数组
json_dict() {
local -n dict=""
declare -A hash_table
append_to_hash_table() {
shift
{ read -r key; read -r value; } <<<""
hash_table+=([$key]="$value")
}
readarray -d $'[=14=]' -c 1 -C append_to_hash_table < <(
# Create nul delimited dict entry using jq
jq -cjn --argjson d "$dict" '$d|to_entries|map("\(.key)\n\(.value|tostring|@sh)")|.[]+"\u0000"'
)
# Here hash_table contain the correct output
dict=""
dict="$hash_table"
}
> unset arr; arr='{"a": "aa", "l": "bb", "c": "ccccc"}'; json_dict arr; echo "${arr[@]}"
Nothing
似乎 dict="$hash_table"
没有正确更新引用名,
如何使 bash dict
refname 指向 hash_table
?
此处不需要 readarray
:您可以将两个单独的 NUL-delimited read
作为 while
循环的一部分。
请参阅 https://replit.com/@CharlesDuffy2/GrandioseDraftyArguments#main.sh
中演示的以下答案
while IFS= read -r -d '' key && IFS= read -r -d '' value; do
hash_table[$key]=$value
done < <(jq -cjn --argjson d "$arr" \
'$d | to_entries[] | ( .key, "\u0000", .value, "\u0000")')
结合上下文:
json_dict() {
declare key value in_value="${!1}"
unset "" # FIXME: Better to take a for output variable
declare -g -A ""
declare -n hash_table=""
while IFS= read -r -d '' key && IFS= read -r -d '' value; do
hash_table[$key]=$value
done < <(
jq -cjn --argjson d "$in_value" \
'$d | to_entries[] | ( .key, "\u0000", .value, "\u0000")'
)
}
arr='{"a": "aa", "l": "bb", "c": "ccccc"}'
json_dict arr
declare -p arr
...作为输出发出:
declare -A arr=([a]="aa" [c]="ccccc" [l]="bb" )
也就是说,要准确回答问题 as-asked,因此使用 readarray
:
json_dict() {
declare -a pieces=()
readarray -d '' pieces < <(
jq -cjn --argjson d "${!1}" \
'$d | to_entries[] | ( .key, "\u0000", .value, "\u0000")'
)
unset ""
declare -g -A ""
declare -n hash_table=""
set -- "${pieces[@]}"
while (( $# )); do
hash_table[]=
{ shift && shift; } || return
done
}
arr='{"a": "aa", "l": "bb", "c": "ccccc"}'
json_dict arr
declare -p arr
只使用 declare
并让 jq
使用 @sh
创建内容以符合 shell 不是更简单吗?
索引数组:
unset arr; arr='["a", "b", "c"]'
declare -a arr="($(jq -r @sh <<< "$arr"))"
关联数组:
unset arr; arr='{"a": "aa", "l": "bb", "c": "ccccc"}'
declare -A arr="($(jq -r 'to_entries[] | @sh "[\(.key)]=\(.value)"' <<< "$arr"))"
对编辑请求的反应:以上要求值是字符串(数字和布尔值也可以),但其他结构需要先转换为字符串格式。特别是,根据请求,@json
可用于将任意 JSON 内容编码为字符串。但是,请记住,在这样做时,bash 数组的项目将是 JSON-encoded,这意味着简单的情况(上面的 aa
之类的字符串)也将被编码(例如,作为"aa"
,包括引号,如 JSON 所要求)。如果这是你想要的,那就去做吧:
具有 JSON-encoded 个值的索引数组:
unset arr; arr='["a", {}, [null, {"a": true}]]'
declare -a arr="($(jq -r 'map(@json) | @sh' <<< "$arr"))"
具有 JSON-encoded 个值的关联数组:
unset arr; arr='{"a": "aa", "b": {"l": "bb", "c": "ccccc"}}'
declare -A arr="($(jq -r 'to_entries[] | @sh "[\(.key)]=\(.value | @json)"' <<< "$arr"))"
首先是数组的工作示例
json_array() {
local -n array=""
readarray -d $'[=13=]' -t array < <(
# Create nul delimited array entry using jq
jq -cjn --argjson arr "$array" '$arr|map(tostring)|.[]+"\u0000"'
)
}
> unset arr; arr='["a", "b", "c"]'; json_array arr; echo "${arr[0]} ${arr[1]} ${arr[2]}"
a b c
现在我正在尝试用 dict 做一些类似的事情,将 json dict 转换成 bash 关联数组
json_dict() {
local -n dict=""
declare -A hash_table
append_to_hash_table() {
shift
{ read -r key; read -r value; } <<<""
hash_table+=([$key]="$value")
}
readarray -d $'[=14=]' -c 1 -C append_to_hash_table < <(
# Create nul delimited dict entry using jq
jq -cjn --argjson d "$dict" '$d|to_entries|map("\(.key)\n\(.value|tostring|@sh)")|.[]+"\u0000"'
)
# Here hash_table contain the correct output
dict=""
dict="$hash_table"
}
> unset arr; arr='{"a": "aa", "l": "bb", "c": "ccccc"}'; json_dict arr; echo "${arr[@]}"
Nothing
似乎 dict="$hash_table"
没有正确更新引用名,
如何使 bash dict
refname 指向 hash_table
?
此处不需要 readarray
:您可以将两个单独的 NUL-delimited read
作为 while
循环的一部分。
请参阅 https://replit.com/@CharlesDuffy2/GrandioseDraftyArguments#main.sh
中演示的以下答案while IFS= read -r -d '' key && IFS= read -r -d '' value; do
hash_table[$key]=$value
done < <(jq -cjn --argjson d "$arr" \
'$d | to_entries[] | ( .key, "\u0000", .value, "\u0000")')
结合上下文:
json_dict() {
declare key value in_value="${!1}"
unset "" # FIXME: Better to take a for output variable
declare -g -A ""
declare -n hash_table=""
while IFS= read -r -d '' key && IFS= read -r -d '' value; do
hash_table[$key]=$value
done < <(
jq -cjn --argjson d "$in_value" \
'$d | to_entries[] | ( .key, "\u0000", .value, "\u0000")'
)
}
arr='{"a": "aa", "l": "bb", "c": "ccccc"}'
json_dict arr
declare -p arr
...作为输出发出:
declare -A arr=([a]="aa" [c]="ccccc" [l]="bb" )
也就是说,要准确回答问题 as-asked,因此使用 readarray
:
json_dict() {
declare -a pieces=()
readarray -d '' pieces < <(
jq -cjn --argjson d "${!1}" \
'$d | to_entries[] | ( .key, "\u0000", .value, "\u0000")'
)
unset ""
declare -g -A ""
declare -n hash_table=""
set -- "${pieces[@]}"
while (( $# )); do
hash_table[]=
{ shift && shift; } || return
done
}
arr='{"a": "aa", "l": "bb", "c": "ccccc"}'
json_dict arr
declare -p arr
只使用 declare
并让 jq
使用 @sh
创建内容以符合 shell 不是更简单吗?
索引数组:
unset arr; arr='["a", "b", "c"]'
declare -a arr="($(jq -r @sh <<< "$arr"))"
关联数组:
unset arr; arr='{"a": "aa", "l": "bb", "c": "ccccc"}'
declare -A arr="($(jq -r 'to_entries[] | @sh "[\(.key)]=\(.value)"' <<< "$arr"))"
对编辑请求的反应:以上要求值是字符串(数字和布尔值也可以),但其他结构需要先转换为字符串格式。特别是,根据请求,@json
可用于将任意 JSON 内容编码为字符串。但是,请记住,在这样做时,bash 数组的项目将是 JSON-encoded,这意味着简单的情况(上面的 aa
之类的字符串)也将被编码(例如,作为"aa"
,包括引号,如 JSON 所要求)。如果这是你想要的,那就去做吧:
具有 JSON-encoded 个值的索引数组:
unset arr; arr='["a", {}, [null, {"a": true}]]'
declare -a arr="($(jq -r 'map(@json) | @sh' <<< "$arr"))"
具有 JSON-encoded 个值的关联数组:
unset arr; arr='{"a": "aa", "b": {"l": "bb", "c": "ccccc"}}'
declare -A arr="($(jq -r 'to_entries[] | @sh "[\(.key)]=\(.value | @json)"' <<< "$arr"))"