我遇到了一个脚本问题。我有以下内容:
~/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的引用,但是我没有找到一个令人满意的答案,因为问题的原因是什么,因此我在问。
答案 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 .