我一直被 Bash 脚本中的变量扩展问题所困扰,当将一个被空格包围的多字参数传递到函数链中时,它会被拆分成多个参数。
例如:
"this entire string"
变成:
"this
entire
string"
从导致问题的代码中提取出函数的排列,下面是我能想到的重现该问题的方法:
#!/usr/bin/env bash
# The function that gets called from outside the script
wrapper_function () {
echo "1: Parameter count: $#"
for i in "$@"; do
echo "wrapper_function - $i"
done
actual_function $@
}
# The actual low-level function that does something useful
actual_function () {
echo "2: Parameter count: $#"
for i in "$@"; do
echo "actual_function - $i"
done
}
# Setting the value of the 'problematic' argument
some_string="\"five-1 five-2\""
# Calling the function with a collated set of arguments
wrapper_function "one two three four ${some_string}"
运行这个我会得到:
1: Parameter count: 1
wrapper_function - one two three four "five-1 five-2"
2: Parameter count: 6
actual_function - one
actual_function - two
actual_function - three
actual_function - four
actual_function - "five-1
actual_function - five-2"
相反,我期望:
1: Parameter count: 1
wrapper_function - one two three four "five-1 five-2"
2: Parameter count: 5
actual_function - one
actual_function - two
actual_function - three
actual_function - four
actual_function - "five-1 five-2"
我能做些什么来解决这个问题,也许引用一些论点或者以其他方式传递它们?
我发现了一个类似问题这个可能看起来像是重复的,但我认为不是。
答案1
只需进行适当的引用
#! /bin/bash
function level3 {
printf -- "-- Level3 ------\nGot %d arguments:\n" $#
for arg in "$@"
do
printf "%s\n" "$arg"
done
printf -- "--------\n"
}
function level2 {
printf -- "-- Level2 ------\nGot %d arguments:\n" $#
for arg in "$@"
do
printf "%s\n" "$arg"
done
printf -- "--------\n"
level3 "$@"
}
function level1 {
printf -- "-- Level1 ------\nGot %d arguments:\n" $#
for arg in "$@"
do
printf "%s\n" "$arg"
done
printf -- "--------\n"
level2 "$@"
}
level1 "$@"
给出:
>>./quotes a bc "\"abc def\""
-- Level1 ------
Got 3 arguments:
a
bc
"abc def"
--------
-- Level2 ------
Got 3 arguments:
a
bc
"abc def"
--------
-- Level3 ------
Got 3 arguments:
a
bc
"abc def"
--------
答案2
好吧,经过一番尝试,我终于自己解决了这个问题,我认为这真的可以帮助遇到这种问题的人。解决方案基本上需要进行两处更改:
- 需要使用两个参数而不是一个参数来调用该函数
wrapper_function
。我会将第一组“常用”参数作为单个字符串传递,然后将“有问题”的参数作为第二组传递。 - 该函数
actual_function
需要将两个接收到的参数分别传递到链中,而不是将整个集合作为引用$@
。
代码现在看起来像这样:
#!/usr/bin/env bash
# The function that gets called from outside the script
wrapper_function () {
echo "1: Parameter count: $#"
for i in "$@"; do
echo "wrapper_function - $i"
done
actual_function $1 "$2"
}
# The actual low-level function that does something useful
actual_function () {
echo "2: Parameter count: $#"
for i in "$@"; do
echo "actual_function - $i"
done
}
# Setting the value of the 'problematic' argument
some_string="\"five-1 five-2\""
# Calling the function with a collated set of arguments
wrapper_function "one two three four" "${some_string}"
虽然输出有些不同,但似乎完成了我想要做的事情:
1: Parameter count: 2
wrapper_function - one two three four
wrapper_function - "five-1 five-2"
2: Parameter count: 5
actual_function - one
actual_function - two
actual_function - three
actual_function - four
actual_function - "five-1 five-2"
我希望有人会发现这很有用。