我的目标是使用变量作为参数来调用脚本。例如,我有以下两个文件:
print_args.sh:
echo "Length: $#"
for i in "$@"; do echo "$i"; done
caller.sh:
ARGS="foo \"Hello, World\" bar"
./test.sh $ARGS
当我跑步时:
./print_args.sh foo "Hello, World" bar
print_args.sh
的调用带有3个参数:
Length 3
foo
Hello, World
bar
但是,当通过caller.sh
运行它时,我得到了4个参数:
Length: 4
foo
"Hello,
World"
bar
这是怎么回事?如何使caller.sh
达到预期效果?
注意:我无法控制它作为环境变量传入的ARGS
。
答案 0 :(得分:3)
如何使test_caller.sh达到预期效果?
使用数组:
#!/bin/bash
args=( foo "Hello, World" bar )
./test.sh "${args[@]}"
如果传递未加引号的变量,则在将其传递给./test.sh
之前,会在其内容上进行单词拆分。您实际上是在打电话:
'./test.sh' 'foo' '"Hello,' 'World"' 'bar'
其中的单引号用于指示单词的开头和结尾。双引号没有语法含义,此时它们只是字符串中的字符。
如果您可以说服脚本用户更改环境变量的格式,则可以基于其他分隔符对其进行拆分:
ARGS="foo:Hello World:bar"
set -f # disable glob expansion
IFS=: args=( $ARGS )
set +f # re-enable it
现在您有了一个数组args
,可以像上面那样使用。
将字符串放入数组的一种(非常讨厌,危险)方法是使用臭名昭著的eval
:
readarray -t args < <(eval printf '%s\\n' $ARGS)
现在您有了一个数组args
,可以像前面的示例中那样使用它。
但这是一个很大的安全问题:
ARGS="foo \"Hello, World\" bar \$(ls -l)"
用您要执行的任何命令替换ls -l
...