当 jq 输出空字符串时 bash readarray -t 数组赋值的问题
Problem with bash readarray -t array assignment when jq outputs an empty string
首先-一个非常简单的代码:
#!/bin/bash
a_string="string"
readarray -t a <<<"$a_string"
echo "${a[@]}"
echo "${#a[@]}"
# read empty string into array
emptystring=""
readarray -t b <<<"$emptystring"
echo "${b[@]}"
echo "${#b[@]}"
# and now - empty array
c=()
echo "${c[@]}"
echo "${#c[@]}"
和输出
string
1
1
0
所以用 readarray -t
将空字符串读入 bash 数组显示数组长度为 1。只有真正的空数组长度为 0。
我的问题 - 为什么会这样?
就我而言 - 这是我脚本中的一个片段 - 执行 API 调用,获取 JSON,然后应用 jq 过滤器:
URL_list_json=$(curl -s --request GET "$curl_request" --header "Authorization: Bearer ${token}")
readarray -t URL_names <<<"$(echo "$URL_list_json" | jq -r '.[].Body.monitors[].name')"
这是一个 JSON 的示例,它从 jq 调用中得到一个空数组:
[
{
"Header": {
"Region": "dc1",
"Tenant": "tenant1",
"Stage": "test"
},
"Body": {
"monitors": []
}
}
]
这里是 JSON 填充内容 return 从 jq 调用中获取一个非空数组:
[
{
"Header": {
"Region": "dc2",
"Tenant": "tenant2",
"Stage": "qa"
},
"Body": {
"monitors": [
{
"enabled": true,
"entityId": "TEST-674BA97E74FC74AA",
"name": "production.example.com"
},
{
"enabled": false,
"entityId": "TEST-3E2D23438A973D1E",
"name": "test.example.com"
}
]
}
}
]
我需要检查 URL_names
数组是否为空。如果不为空,则遍历内容。如果为空 - 表示 jq 没有 return 任何结果 - 白色以登录并继续。
如果我使用 if ((${#URL_names[@]}))
作为检查数组是否为空的方法,即使数组只有来自 jq 调用的空字符串,它也会 return 1 ,所以这逻辑错误。
处理上述情况的替代方法是什么?
我可以将 jq 过滤器的输出分配给一个字符串,然后使用 if 语句检查字符串是否为空,如果非空则将字符串分配给一个数组,但这会引入额外的元素。通过这种方法,我可以完全跳过使用数组——我希望只使用数组来完成这项任务。
谢谢
why it is happening?
因为它读一行。来自 bash manual here document:
[n]<<< word
[...] The result is supplied as a single string, with a newline appended, to the command on its standard input (or file descriptor n if n is specified).
因为有一个换行符,所以readarray
读取一个空行。你可以这样做:
readarray -t b < <(printf "%s" "$emptystring")
备注:
echo "$var"
不是首选。在 posix shell 中执行 printf "%s" "$var"
,在 bash 中执行 <<<"$var"
(并且您不关心额外的换行符)。
<<<"$(...)"
总是看起来很奇怪 - <<<
无论如何都必须分配一个 subshell。做 < <(...)
.
- 你想做的事:
readarray -t URL_names < <(<<<"$URL_list_json" jq -r '.[].Body.monitors[].name')
- 如果要检查数组是否为空,请在
jq
中进行检查。 I see ex. jq --exit-status '.[].Body.monitors[].name'
并检查退出状态。
首先-一个非常简单的代码:
#!/bin/bash
a_string="string"
readarray -t a <<<"$a_string"
echo "${a[@]}"
echo "${#a[@]}"
# read empty string into array
emptystring=""
readarray -t b <<<"$emptystring"
echo "${b[@]}"
echo "${#b[@]}"
# and now - empty array
c=()
echo "${c[@]}"
echo "${#c[@]}"
和输出
string
1
1
0
所以用 readarray -t
将空字符串读入 bash 数组显示数组长度为 1。只有真正的空数组长度为 0。
我的问题 - 为什么会这样?
就我而言 - 这是我脚本中的一个片段 - 执行 API 调用,获取 JSON,然后应用 jq 过滤器:
URL_list_json=$(curl -s --request GET "$curl_request" --header "Authorization: Bearer ${token}")
readarray -t URL_names <<<"$(echo "$URL_list_json" | jq -r '.[].Body.monitors[].name')"
这是一个 JSON 的示例,它从 jq 调用中得到一个空数组:
[
{
"Header": {
"Region": "dc1",
"Tenant": "tenant1",
"Stage": "test"
},
"Body": {
"monitors": []
}
}
]
这里是 JSON 填充内容 return 从 jq 调用中获取一个非空数组:
[
{
"Header": {
"Region": "dc2",
"Tenant": "tenant2",
"Stage": "qa"
},
"Body": {
"monitors": [
{
"enabled": true,
"entityId": "TEST-674BA97E74FC74AA",
"name": "production.example.com"
},
{
"enabled": false,
"entityId": "TEST-3E2D23438A973D1E",
"name": "test.example.com"
}
]
}
}
]
我需要检查 URL_names
数组是否为空。如果不为空,则遍历内容。如果为空 - 表示 jq 没有 return 任何结果 - 白色以登录并继续。
如果我使用 if ((${#URL_names[@]}))
作为检查数组是否为空的方法,即使数组只有来自 jq 调用的空字符串,它也会 return 1 ,所以这逻辑错误。
处理上述情况的替代方法是什么?
我可以将 jq 过滤器的输出分配给一个字符串,然后使用 if 语句检查字符串是否为空,如果非空则将字符串分配给一个数组,但这会引入额外的元素。通过这种方法,我可以完全跳过使用数组——我希望只使用数组来完成这项任务。
谢谢
why it is happening?
因为它读一行。来自 bash manual here document:
[n]<<< word
[...] The result is supplied as a single string, with a newline appended, to the command on its standard input (or file descriptor n if n is specified).
因为有一个换行符,所以readarray
读取一个空行。你可以这样做:
readarray -t b < <(printf "%s" "$emptystring")
备注:
echo "$var"
不是首选。在 posix shell 中执行printf "%s" "$var"
,在 bash 中执行<<<"$var"
(并且您不关心额外的换行符)。<<<"$(...)"
总是看起来很奇怪 -<<<
无论如何都必须分配一个 subshell。做< <(...)
.- 你想做的事:
readarray -t URL_names < <(<<<"$URL_list_json" jq -r '.[].Body.monitors[].name')
- 如果要检查数组是否为空,请在
jq
中进行检查。 I see ex.jq --exit-status '.[].Body.monitors[].name'
并检查退出状态。