bash 中具有动态结果的动态变量

bash 中具有动态结果的动态变量

dubdub_count=3

for (( i=1; i<=${dubdub_count}; i++ )); do
  my_apps --ammount=${dubdub_count}
done

程序将返回 IP 地址示例结果

app1=10.10.10.1
app2=10.10.10.2
app3=10.10.10.3

这些IP地址将用于其他服务。我正在创建一个 apiserver.sh bash 脚本来运行 apiserver 命令,如下所示

/usr/local/bin/apiserver --dubdub=http://${app1},http://${app2},http://{app3} --master

我希望我的 apiserver.sh 能够从 my_apps 结果添加动态结果。

如果我更改dubdub_count=3dubdub_count=4 我的脚本必须能够像这样运行

/usr/local/bin/apiserver --dubdub=http://10.10.10.1:8080,http://10.10.10.2:8080,http://10.10.10.3,http://10.10.10.4 --master

如果我更改dubdub_count=3dubdub_count=5 我的脚本必须能够像这样运行

/usr/local/bin/apiserver --dubdub=http://10.10.10.1:8080,http://10.10.10.2:8080,http://10.10.10.3:8080,http://10.10.10.4:8080,http://10.10.10.5:8080 --master

摘要问题是如何将 my_app 结果自动添加到--dubdub参数中?如果 my_app 返回 6 个 IP 地址,我的 --dubdub 也将获得 6 个 IP 地址。我不需要手动编辑 bash 脚本。

我已经dynamic var in bash在 stackoverflow 中阅读了 as 关键字,但仍然找不到最佳解决方案。我应该建议 my_apps 开发人员更改结果方法吗?

答案1

您可以添加http://:8080使用sed, 然后paste -sd,将它们放在一起并用逗号分隔:

urllist=$(
  for ... done \
  | cut -d= -f2 \
  | sed 's#.*#http://&:8080#' \
  | paste -sd, -
) # output: http://10.10.10.1:8080,http://10.10.10.2:8080,http://10.10.10.3:8080
/usr/local/bin/apiserver --dubdub="$urllist" --master

cut或者在一个命令中将,sedpastepart 一起执行awk

urllist=$(
  for ... done \
  | awk -F= 'NR>1{printf ","};{printf "http://"$2":8080"}'
) # output: http://10.10.10.1:8080,http://10.10.10.2:8080,http://10.10.10.3:8080
/usr/local/bin/apiserver --dubdub="$iplist" --master

答案2

从...开始:

$ seq -f "http://10.10.10.%g:8080" 1 3
http://10.10.10.1:8080
http://10.10.10.2:8080
http://10.10.10.3:8080

然后你可以把它变成一个函数:

$ ddcount() { seq -f "http://10.10.10.%g:8080" "$@" ; }
$ ddcount 5 7
http://10.10.10.5:8080
http://10.10.10.6:8080
http://10.10.10.7:8080

(注意:因为这只是将所有参数传递给命令seq,所以 FIRST 参数是可选的,默认为 1。 ieseq 3与 相同seq 1 3, 与ddcount 3相同ddcount 1 3。如果需要,您也可以指定增量。请参阅man seq详情)

将其与另一个函数结合使用分隔符(例如逗号)连接参数:

$ join_by() { local d=$1; shift; printf '%s' "$1"; shift; printf '%s' "${@/#/$d}"; }

这是以 perljoin()函数为模型的,但命名join_by是为了不与join命令冲突。第一个参数是分隔符。其余参数是要连接的数据。

$ join_by , $(ddcount 1 3)
http://10.10.10.1:8080,http://10.10.10.2:8080,http://10.10.10.3:8080

注意:不要对$(ddcount 1 3)函数调用使用双引号 - 你它返回的字符串将被分词为多个项目,而不是仅被视为一个长字符串。比较上述命令的输出以join_by , "$(ddcount 1 3)"查看差异。

最后,将所有这些放在一起:

start=1; stop=3
/usr/local/bin/apiserver --dubdub="$(join_by , $(ddcount "$start" "$stop"))" --master

或者

dd="$(join_by , $(ddcount "$start" "$stop"))"
/usr/local/bin/apiserver --dubdub="$dd" --master

答案3

假设您可以将第一个循环放入其自己的脚本中或放入名为的 shell 函数中my_apps_loop(或者您可以将其插入到my_apps_loop下面的调用中)。

#!/bin/bash

urls=()

# Create URLs
while IFS='=' read -r app ip; do
    urls+=( "http://$ip:8080" )
done < <(my_apps_loop)

(
    IFS=','

    # Call apiserver with generated URLs
    /usr/local/bin/apiserver --dubdub="${urls[*]}" --master
)

这将循环读取部分 into的输出my_apps_loop(这将输出带有app1=...等的行)以及into后面的字符串。appN$app=$ip

对于读取的每一行,该$ip位都会以字符串 开头http://,以 为后缀:8080,并插入到数组 中urls

最后的子 shell 调用apiserver.该--dubdub选项从urls数组中获取其值,并将数组的值连接成一个以逗号分隔的字符串。

相关内容