浏览过这篇文章:完全按原样将参数传递给函数
但设置略有不同:
我有 3 个 bash 函数 foo、bar、baz。它们的设置如下:
foo() {
bar $1
}
bar() {
var1=$1
var2=$2
echo "$var1" test "$var2"
}
export ENV_VAR_1="1"
export ENV_VAR_2="2 3"
foo "${ENV_VAR_1} ${ENV_VAR_2}"
我期望输出是:
1 test 2 3
但输出是:
1 test 2
我明白为什么会这样。 bar 执行如下:
bar 1 2 3
我的问题是:如何让它执行
bar 1 "2 3"
我尝试过的方法:
foo () {bar "$1"}
# Out: 1 2 3 test. Makes sense since "1 2 3" is interpreted as a single argument.
答案1
这提供了一个字符串作为参数foo
:
foo "${ENV_VAR_1} ${ENV_VAR_2}"
因为$1
不在引号中,所以 shell 执行分词,因此,这为 提供了三个参数bar
:
bar $1
分词是对S1
.不考虑这些字符的原始来源。
更简单的例子
让我们定义x
为:
$ x="${ENV_VAR_1} ${ENV_VAR_2}"
现在,让我们打印"$x"
:
$ printf "%s\n" "$x"
1 2 3
正如您所看到的,"$x"
被解释为一个参数。相比之下,请考虑:
$ printf "%s\n" $x
1
2
3
在上面,分词是在$x
创建三个参数时执行的。
Shell 字符串没有历史的概念。字符串在被分配之前x
没有2 3
作为一个字符串的一部分的记录。x
字符串x
仅由1
、 空格、2
、 空格组成,3
并且分词对空格进行操作。
替代方案:选择您自己的 IFS
这会产生您想要的输出:
$ foo() ( IFS=@; bar $1; )
$ foo "${ENV_VAR_1}@${ENV_VAR_2}"
1 test 2 3
在 中foo
,我们设置IFS
为@
。因此,所有后续的单词分割都是使用@
单词分隔符来执行的。因此,在调用 时foo
,我们将 a 放在@
需要分词的任何位置。
答案2
您向函数传递一个参数foo
,即 5 个字符的字符串1 2 3
。三个数字之间用空格分隔。foo
没有理由以不同的方式对待这些空间。
在组合${ENV_VAR_1}
和${ENV_VAR_2}
内部单个字符串中,您丢失了信息。恢复丢失的信息需要魔法,而计算机无法做到这一点。要保留1 2
和之间的分离3
,您需要更改foo
调用方式。传递两个单独的参数。
foo "${ENV_VAR_1}" "${ENV_VAR_2}"
那么你需要做的就是修复引用在呼叫中bar
。要么传递两个参数:
foo () {
bar "$1" "$2"
}
或传递整个参数列表:
foo () {
bar "$@"
}