我已经看到grep
命令的两个版本:
根据上述链接,一种格式是(它以gmtime_r
作为模式):
git grep -n gmtime_r
与此相反(它寻找UNix
作为模式):
grep -i "UNix" geekfile.txt
有人可以指出我们何时需要使用""
,何时可以跳过它们?
谢谢。
[因为我在这两个方面都遇到了这个问题,所以标记了Linux和MacOS,我认为这对两者都适用。]
答案 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_r
和grep -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。