[英]Assigning “$@” to a variable in Bash and preserving escaping
If I save the following script as 'args.bash' and run bash args.bash -a 'foo bar'
如果我将以下脚本另存为'args.bash'并运行
bash args.bash -a 'foo bar'
#!/bin/bash
main() {
set -x
which "$@"
local args="$@"
which "$args"
which $args
local args=$(printf " %q" "$@")
which "$args"
which $args
}
main "$@"
I'm surprised to see that these print different results. 我很惊讶地看到这些打印出不同的结果。 The first one prints:
第一个打印:
which -a 'foo bar'
Which I expect! 我期望的! It groups the arguments properly.
它将参数正确分组。
The rest of them print, in order: 其余的按顺序打印:
which '-a foo bar'
which -a foo bar
which ' -a foo\ bar'
which -a 'foo\' bar
Which are all incorrect to one degree or another. 在某种程度上都是不正确的。 How can I assign
"$@"
to a variable, and get it to echo the same output as the first command? 如何为变量分配
"$@"
,并使其回显与第一个命令相同的输出?
Use an array variable, not a scalar: 使用数组变量,而不是标量:
items=( "$@" )
which -a "${items[@]}"
However, if you must use a scalar [1] , you had the right approach with printf '%q '
; 但是,如果必须使用标量[1] ,则可以正确地使用
printf '%q '
; note, however, that printf %q
creates a string which will evaluate back to itself when run through the full parser (thus requiring eval
or an equivalent to ensure that the full parser is invoked): 但是请注意,
printf %q
创建了一个字符串,该字符串将在通过完整解析器运行时对其求值(因此需要eval
或等效项才能确保调用完整解析器):
printf -v items_str '%q ' "$@"
eval "which -a $items_str"
[1] The number of circumstances where one has bash extensions such as printf -v
and %q
but can't use an array is limited, but they do exist; [1]具有bash扩展名(例如
printf -v
和%q
但不能使用数组的情况数量有限,但它们确实存在; particularly, passing values to a subprocess through the environment comes to mind. 特别是想到通过环境将值传递给子流程。 However, in the bulk of cases where arrays are inappropriate, I'd expect either using a series of distinct environment variables (one per value), or passing a NUL-delimited stream (as created by
printf '%s\\n' "$@"
) to be more appropriate, even if (as for the environment) it might need to be escaped (for instance, via base64-encoding). 但是,在大多数情况下,数组不合适,我希望使用一系列不同的环境变量(每个值一个),或者传递NUL分隔的流(由
printf '%s\\n' "$@"
)更合适,即使(对于环境而言)可能需要转义(例如,通过base64-encoding)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.