将"$@"存储到变量以供以后使用,并遵循引用的参数

  • 本文关键字:引用 参数 存储 变量 bash
  • 更新时间 :
  • 英文 :


我有一个用bash编写的项目。接口的一部分要求用户使用间接层调用bash函数,如下所示:

require some_fun "arg 1" "arg 2"

它执行some_fun "arg 1" "arg 2"(然后做一些额外的事情,因此它存在)。目前我只是调用"$@"来做这件事,一切都正常工作。

我现在需要这些函数调用推迟到以后,并且在Bash中找不到这样做的方法。实际上,我想在每次调用require时将"$@"推送到堆栈上,然后在该堆栈上循环并执行参数,就像我当前的行为一样。这需要多维数组,bash不支持,所以我尝试这样做:

require() {
dep_num=${#SK_deps[@]}
dep_var="SK_dep_$dep_num"
eval $dep_var="$@"
SK_deps+=($dep_var)
}

它基本上生成一个变量变量来存储"$@",并将变量名放在$SK_deps中。

然后我尝试用迭代列表

for dep_var in ${SK_deps[@]}
do
${!dep_name}
done

但这似乎打破了引用的论点,所以:

require some_fun "arg 1" "arg 2"

解释为:

require some_fun arg 1 arg 2

没有引号。

有什么办法做我想做的事吗?使用"$*"还会导致报价定位的损失。感觉应该有一种方法可以在Bash中做到这一点,而不需要使用sed/awk。

eval解决方案还不错。关键是利用printfshell引用机制,它将为您处理所有棘手的情况:

require() {
local quoted
printf -v quoted ' %q' "$@"
SK_deps+=("$quoted")
}

然后你就可以正常运行了:

for dep in "${SK_deps[@]}"; do eval $dep; done

展开数组时引用数组:

for dep_var in "${SK_deps[@]}"
do
${!dep_name}
done

同样,下面这句话似乎很可疑:

eval $dep_var="$@"

试着用set -xv运行脚本,看看变量是如何真正扩展的。

我发现了一个使用eval的非常丑陋的解决方案,因此任何更好的建议都将不胜感激。

require() {
local tmp_var=""
for arg in "$@"
do
tmp_var="$tmp_var "$arg""
done
SK_deps+=("$tmp_var")
}

然后:

for dep in "${SK_deps[@]}"
do
eval $dep
done

很明显,像这样使用eval充满了边缘情况,比如参数中已经有引号,或者参数中已经存在反斜杠,等等。

相关内容

  • 没有找到相关文章

最新更新