Bash 参数扩展、间接引用和背景
Bash parameter expansion, indirect reference, and backgrounding
在为这个问题苦苦挣扎了几个小时并在这里搜索并没有找到匹配的解决方案之后,是时候问一下了:
在 bash (4.3) 中,我尝试组合执行以下操作:
- 创建数组
- For 使用不是超快的命令循环遍历数组的值(卷曲到 Web 服务器以获取值),因此我们将每个循环置于后台以并行化所有内容以加快速度。
- 将数组中值的 names 设置为分配给通过 "read"
从命令重定向到它的值的变量
- 背景每个循环并将它们的 PID 放入常规数组中, 和 将每个 PID 与关联数组中的相关数组值相关联,所以我有数组值的键=值对PID 的名称
- 使用"wait"等待每个PID退出0或抛出错误告诉我们数组中的哪些值名称未能通过引用关联数组以0退出
- 我需要能够导出原始数组中的所有 VAR 名称及其现在关联的值(来自 curl 命令结果),因为我从另一个 bash 脚本中获取此脚本使用导出的结果 VARs/values.
我使用 "read" 而不是仅使用 "export" 和 "export var=$(command)" 或类似的原因是因为当我后台并获取 PID 以使用 "wait" 时在下一个 for 循环中,我实际上(错误地)得到了总是以 0 退出的 "export" 命令的 PID,所以我没有检测到错误。当我使用带有重定向的读取来设置 VAR 的值(来自数组中的名称)和背景时,它实际上获取了命令的 PID,并且我在下一个循环中使用 "wait" 命令捕获了任何错误。
所以,基本上,这似乎大部分都有效, 除了 我意识到 "read" 命令实际上并没有将变量替换为数组名称值以重定向命令将其输出发送到该名称的方式正确,以便将替换的 VAR 名称设置为一个值。或者,也许命令完全错误,所以我没有正确地将我的命令结果重定向到我试图设置的 VAR 名称。
为了它的价值,当我 运行 卷曲 | python 手动命令(提取值然后解析 JSON 输出)它肯定是成功的,所以我知道这是有效的,我只是无法获得重定向以将结果输出发送到VAR 名称。
这是我正在尝试做的一个例子:
在父脚本中:
# Source the child script that has the functions I need
source functions.sh
# Create the array
VALUES=(
VALUE_A
VALUE_B
VALUE_C
)
# Call the function sourced from the script above, which will use the above defined array
function_getvalues
在子(来源)脚本中:
function_getvalues()
{
curl_pids=( )
declare -A value_pids
for value in "${VALUES[@]}"; do
read ${value} < <(curl -f -s -X GET http://path/to/json/value | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['value'])") & curl_pids+=( $! ) value_pids+=([$!]=${value})
done
for pid in "${curl_pids[@]}"; do
wait "$pid" && echo "Successfully retrieved value ${value_pids[$pid]} from Webserver." || { echo "Something went wrong retrieving value ${value_pids[$pid]}, so we couldn't get the output data needed from Webserver. Exiting." ; exit 1 ; }
done
}
问题是 read
,当 运行 在后台时,isn't connected to a standard in.[details] 考虑这个简化的工作示例,并评论如何削弱它:
VALUES=( VALUE_A VALUE_B )
for value in "${VALUES[@]}"; do
read ${value} < <(echo ${RANDOM}) # add "&" and it stops working
done
echo "VALUE_A=${VALUE_A}"
echo "VALUE_B=${VALUE_B}"
你可能可以用coproc
, or using 做到这一点,但实际上这是临时文件的工作:
tmpdir=$(mktemp -d)
VALUES=( VALUE_A VALUE_B )
for value in "${VALUES[@]}"; do
(sleep 1; echo ${RANDOM} > "${tmpdir}"/"${value}") &
done
for value in "${VALUES[@]}"; do
wait_file "${tmpdir}"/"${value}" && {
read -r ${value} < "${tmpdir}"/"${value}";
}
done
echo "VALUE_A=${VALUE_A}"
echo "VALUE_B=${VALUE_B}"
rm -r "${tmpdir}"
此示例使用 wait_file
helper,但如果您不介意对 OS 的某些依赖,则可以使用 inotifywait
。
在为这个问题苦苦挣扎了几个小时并在这里搜索并没有找到匹配的解决方案之后,是时候问一下了:
在 bash (4.3) 中,我尝试组合执行以下操作:
- 创建数组
- For 使用不是超快的命令循环遍历数组的值(卷曲到 Web 服务器以获取值),因此我们将每个循环置于后台以并行化所有内容以加快速度。
- 将数组中值的 names 设置为分配给通过 "read" 从命令重定向到它的值的变量
- 背景每个循环并将它们的 PID 放入常规数组中, 和 将每个 PID 与关联数组中的相关数组值相关联,所以我有数组值的键=值对PID 的名称
- 使用"wait"等待每个PID退出0或抛出错误告诉我们数组中的哪些值名称未能通过引用关联数组以0退出
- 我需要能够导出原始数组中的所有 VAR 名称及其现在关联的值(来自 curl 命令结果),因为我从另一个 bash 脚本中获取此脚本使用导出的结果 VARs/values.
我使用 "read" 而不是仅使用 "export" 和 "export var=$(command)" 或类似的原因是因为当我后台并获取 PID 以使用 "wait" 时在下一个 for 循环中,我实际上(错误地)得到了总是以 0 退出的 "export" 命令的 PID,所以我没有检测到错误。当我使用带有重定向的读取来设置 VAR 的值(来自数组中的名称)和背景时,它实际上获取了命令的 PID,并且我在下一个循环中使用 "wait" 命令捕获了任何错误。
所以,基本上,这似乎大部分都有效, 除了 我意识到 "read" 命令实际上并没有将变量替换为数组名称值以重定向命令将其输出发送到该名称的方式正确,以便将替换的 VAR 名称设置为一个值。或者,也许命令完全错误,所以我没有正确地将我的命令结果重定向到我试图设置的 VAR 名称。
为了它的价值,当我 运行 卷曲 | python 手动命令(提取值然后解析 JSON 输出)它肯定是成功的,所以我知道这是有效的,我只是无法获得重定向以将结果输出发送到VAR 名称。
这是我正在尝试做的一个例子: 在父脚本中:
# Source the child script that has the functions I need
source functions.sh
# Create the array
VALUES=(
VALUE_A
VALUE_B
VALUE_C
)
# Call the function sourced from the script above, which will use the above defined array
function_getvalues
在子(来源)脚本中:
function_getvalues()
{
curl_pids=( )
declare -A value_pids
for value in "${VALUES[@]}"; do
read ${value} < <(curl -f -s -X GET http://path/to/json/value | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['value'])") & curl_pids+=( $! ) value_pids+=([$!]=${value})
done
for pid in "${curl_pids[@]}"; do
wait "$pid" && echo "Successfully retrieved value ${value_pids[$pid]} from Webserver." || { echo "Something went wrong retrieving value ${value_pids[$pid]}, so we couldn't get the output data needed from Webserver. Exiting." ; exit 1 ; }
done
}
问题是 read
,当 运行 在后台时,isn't connected to a standard in.[details] 考虑这个简化的工作示例,并评论如何削弱它:
VALUES=( VALUE_A VALUE_B )
for value in "${VALUES[@]}"; do
read ${value} < <(echo ${RANDOM}) # add "&" and it stops working
done
echo "VALUE_A=${VALUE_A}"
echo "VALUE_B=${VALUE_B}"
你可能可以用coproc
, or using
tmpdir=$(mktemp -d)
VALUES=( VALUE_A VALUE_B )
for value in "${VALUES[@]}"; do
(sleep 1; echo ${RANDOM} > "${tmpdir}"/"${value}") &
done
for value in "${VALUES[@]}"; do
wait_file "${tmpdir}"/"${value}" && {
read -r ${value} < "${tmpdir}"/"${value}";
}
done
echo "VALUE_A=${VALUE_A}"
echo "VALUE_B=${VALUE_B}"
rm -r "${tmpdir}"
此示例使用 wait_file
helper,但如果您不介意对 OS 的某些依赖,则可以使用 inotifywait
。