If I save the following script as 'args.bash' and run 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 '
; 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 -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; 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).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.