Bash嵌套引用变量不起作用

时间:2014-12-16 17:38:51

标签: linux bash

我遇到了一个脚本问题。我有以下内容:

~/test> echo bar > foo.txt; echo bar > foo.c
~/test> flags="--include \"*.txt\""
~/test> echo $flags
--include "*.txt"
~/test> grep -rHI $flags bar .
~/test> grep -rHI --include "*.txt" bar .
./foo.txt:bar

所以,基本上grep -rHI $flags bar .的评估与grep -rHI --include "*.txt" bar .不同。有一种解决方法(使用eval),但我有兴趣了解为什么$ flags的处理方式不同于在这种情况下的字面扩展。


显然,这被标记为重复。引用的问题涉及元素之间的空白,而这个问题是关于扩展的优先级,正如choroba指出的那样。 (这两个似乎有相同的解决方案)。我发现了几个使用eval / array的引用,但是我没有找到一个令人满意的答案,因为问题的原因是什么,因此我在问。

2 个答案:

答案 0 :(得分:2)

不同行为的原因是扩展的顺序:

  

扩展在分割为单词后在命令行上执行。 [...]扩展的顺序是:支撑扩展,波浪扩展,参数,变量和算术          扩展和命令替换(以从左到右的方式完成),单词拆分和路径名          扩张。 [...]只有大括号扩展,单词拆分和路径名扩展才能改变单词的数量          扩张;其他扩展将单个单词扩展为单个单词。唯一的例外是          "$@""${name[@]}"

的扩展
但是,

flags=--include=*.txt应该是安全的,除非您在某处有一个名为--include=123.txt的文件,您可以通过在命令中引用"$flags"来阻止该文件。但是,正如引用的文档最后所说,如果有多个标志,使用数组是最好的解决方案:

flags=(--include '*.txt')
grep -rHi "${flags[@]}" bar .

答案 1 :(得分:2)

使用数组是唯一的规范正确的泛型答案,用于传递多个参数并保留其原始边界。

flags=( --include '*.txt' )
grep -rHi "${flags[@]}" bar .