2015-08-28 10 views
0

如果我救下面的脚本为“args.bash”和运行bash args.bash -a 'foo bar'

#!/bin/bash 

main() { 
    set -x 
    which "[email protected]" 

    local args="[email protected]" 
    which "$args" 
    which $args 

    local args=$(printf " %q" "[email protected]") 
    which "$args" 
    which $args 
} 
main "[email protected]" 

我很惊讶地看到,这些打印不同的结果。第一个打印:

which -a 'foo bar' 

我期望!它将正确的参数分组。

他们其余的打印,依次是:

which '-a foo bar' 
which -a foo bar 
which ' -a foo\ bar' 
which -a 'foo\' bar 

这都是不正确的或多或少。我如何将"[email protected]"分配给一个变量,并让它回显与第一个命令相同的输出?

+2

你不能在字符串中存储任意的命令/参数,并保持正确的引号/等。参见[Bash FAQ 050](http://mywiki.wooledge.org/BashFAQ/050)讨论这个问题。你需要使用一个数组。 –

+0

好吧 - 他正在使用'printf%q',它改变了一些东西,但是一个数组仍然是正确的。 –

+0

'printf%q'是我知道的唯一尝试 - 打开任何其他建议。 –

回答

4

使用数组变量,而不是一个标量:

items=("[email protected]") 
which -a "${items[@]}" 

但是,如果必须使用标 [1],你有没有和printf '%q '正确的方法;但是请注意,这printf %q创建时通过充分解析器运行(因此需要eval或等效,以确保充分的解析器调用),这将评估回本身字符串:

printf -v items_str '%q ' "[email protected]" 
eval "which -a $items_str" 

[1]其中一个具有bash扩展名(如printf -v%q但不能使用数组)的情况数量有限,但它们确实存在;特别是通过环境将价值传递给子过程时,我想到了这一点。然而,在数组不合适的情况下,我希望使用一系列不同的环境变量(每个值一个),或者传递NUL分隔的流(由printf '%s\n' "[email protected]"创建)更合适,即使(至于环境),它可能需要转义(例如,通过base64编码)。

+0

呃,所以你必须在那里使用eval? –

+0

如果你不想做正确的事情并使用数组,是的。 –

+0

很酷,谢谢!超级整洁! –