什么时候需要在外壳程序中的命令参数周围使用引号?

时间:2018-10-28 02:59:06

标签: linux macos

我已经看到grep命令的两个版本:

一个here和另一个here

根据上述链接,一种格式是(它以gmtime_r作为模式):

git grep -n gmtime_r

与此相反(它寻找UNix作为模式):

grep -i "UNix" geekfile.txt

有人可以指出我们何时需要使用"",何时可以跳过它们?

谢谢。

[因为我在这两个方面都遇到了这个问题,所以标记了Linux和MacOS,我认为这对两者都适用。]

3 个答案:

答案 0 :(得分:0)

除非您要查找具有嵌入式空格或外壳元字符的模式,否则无需在引人注目的文本周围使用引号。

答案 1 :(得分:-1)

检查一下:

$ cd /tmp/example/
$ touch a b c
$ x="var name"
$ for i in "* $x"; do echo -$i-; done
-* var name-
$ for i in * $x; do echo -$i-; done
-a-
-b-
-c-
-var-
-name-
$ for i in * "$x"; do echo -$i-; done
-a-
-b-
-c-
-var name-
$ for i in * '$x'; do echo -$i-; done
-a-
-b-
-c-
-$x-

答案 2 :(得分:-1)

简短摘要:您可以在引数周围加上引号,以防止外壳在传递给程序之前弄乱引号(例如grep)。外壳上有许多具有特殊含义的字符和模式,在它们周围加上引号可以防止(或限制)这些特殊含义。

您给出的示例git grep -n gmtime_rgrep -i "UNix" geekfile.txt不涉及任何这些特殊字符,因此引用无效。以下所有命令都做完全相同的事情:

grep -i UNix geekfile.txt
grep -i "UNix" geekfile.txt
grep "-i" 'UNix' "geekfile.txt"
grep "-"i UNix "geek"'file'.txt

请注意,如最后一个示例所示,您还可以引用一个参数的一部分,甚至在同一参数中混合使用不同的引用类型(单引号或双引号)。

要查看发生了什么,您可以创建一个shell函数,该函数将打印它获取的参数,然后运行实验。这是一个来自shell会话的示例shell:

$ printargs() { if [ $# -eq 0 ]; then echo "No arguments"; else printf '  <<%s>>\n' "$@"; fi; }
$ printargs -i UNix geekfile.txt
  <<-i>>
  <<UNix>>
  <<geekfile.txt>>
$ printargs "-"i UNix "geek"'file'.txt
  <<-i>>
  <<UNix>>
  <<geekfile.txt>>

如您所见,这些引号无效。但是还有许多其他字符会影响报价:

$ printargs ".*" "foo{1,2}bar"
  <<.*>>
  <<foo{1,2}bar>>
$ printargs .* foo{1,2}bar
  <<.>>
  <<..>>
  <<.DS_Store>>
  <<foo1bar>>
  <<foo2bar>>

带引号的字符串.*foo{1,2}bar仅作为参数直接传递。没有它们,*字符将被视为文件名通配符,它​​将字符串替换为当前目录中以“。”开头的文件列表。 foo{1,2}bar进行了括号扩展,这...嗯,您可以看到它做了什么。 grep模式通常包含特殊字符(例如“ *”),这些特殊字符将由外壳程序解释,因此您真的想引用它们。因此,出于习惯,在grep命令中引用该模式是很常见的,即使该特定模式不是必需的。

单引号和双引号也不同。单引号可防止 all 特殊字符处理(查找闭合引号除外)。双引号允许一些替换(通常以$\和反引号开头的替换)。使用变量时,几乎总是希望在其周围加上双引号,以防止shell弄乱结果字符串:

grep $pattern $filename        # Unsafe -- depending on what's in the variables, weird things might happen
grep "$pattern" "$filename"    # Good -- variables will not be messed with
grep '$pattern' '$filename'    # Wrong -- variables will not be used, just the literal strings

有关单引号和双引号之间的区别,请参见this question,有关双引号变量引用的更多信息,请参见this one