有什么区别
引号仅包围选项值
例如:
grep --file="grep pattern file.txt" *
与
选项名称和选项值用引号括起来
例如:
grep "--file=grep pattern file.txt" *
?
它们产生相同的结果。
答案1
shell 中的引号和反斜杠用于消除某些字符的特殊性,以便将它们视为普通字符。
双引号的特殊之处在于它们仍然允许在其中进行扩展。或者换句话说,在它们之中$
、\
、 和`
仍然是特殊的。它们还会影响这些扩展的执行方式。
在该行中,shell 唯一的特殊字符是:
- 空格,在 shell 的语法中(就像在许多语言中一样)用于分隔语法中的单词,特别是对于该行,参数简单的命令(这是 shell 知道的几个结构之一,也是主要结构)。
- 末尾的换行符(除其他外)用于分隔命令
*
,这是一个全局模式运算符,并且这样一个字符的存在,当不在简单的命令行中引用时,会触发一种称为文件名生成或者通配或者路径名扩展(POSIX 措辞)。
其他字符在 shell 语法中没有特殊意义。
在这里,我们想要做的是让 shell 使用/usr/bin/grep
这些参数执行该文件:
grep
--file=grep pattern file.txt
- 以及以下内容:当前工作目录中的文件列表。
所以我们确实想要:
- 空间被视为这些之间的单词分隔符
- 新队界定该命令
*
被视为全局运算符并扩展到当前工作目录中的非隐藏文件。
所以上面的那些字符一定不能被引用。
然而,其中有两个空间我们希望包含在传递给 的第二个参数中grep
,因此必须引用它们。所以至少,我们需要:
grep --file=grep' 'pattern' 'file.txt *
或者:
grep --file=grep" "pattern\ file.txt *
(显示不同的引用运算符)
在这里,我们只引用 shell 特有的 2 个字符,并且我们不希望将其视为这样。但我们也可以这样做:
'grep' '--file=grep pattern file.txt' *
并报价全部除了我们希望 shell 特殊处理的字符之外的字符。
引用这些非特殊字符对 shell 没有任何影响。
'g'r"ep" \-\-"file="'grep p'atte'\r\n\ file.txt *
在这里交替使用不同形式的引号将起到相同的作用。
鉴于命令和选项²名称很少包含 shell 特殊字符,因此习惯上不引用它们。你很少看到人们用'ls' '-l'
of 代替ls -l
,所以这grep --file="the value"
是一种常见的现象,即使它与grep "--file=the value"
or相比没有什么区别grep --file=the" value"
。
看如何在 Unix shell 中像普通字符一样使用特殊字符?有关哪些字符是特殊的以及在各种 shell 中引用它们的方法的更多详细信息。
现在该命令仍然存在一些问题:
- 如果第一个扩展的文件名以
*
开头-
,它将被视为一个选项 *
展开所有文件,无论其类型如何。其中包括目录、符号链接、fifo、设备。您很可能只想查看以下类型的文件常规的(或者可以符号链接到常规文件)--file
是一个GNU主义。标准等效项是-f
.- 如果
*
仅扩展为一个文件,grep
则不会包含文件名以及匹配行。 - 如果
*
不匹配任何文件,在包括 bash(默认情况下)在内的一些 shell 中,*
将传递一个文字参数grep
(并且它可能会抱怨无法打开该名称的文件)。
因此,在这里,您想使用 zsh shell 为例,并编写:
grep -f 'grep pattern file.txt' -- /dev/null *(-.)
在哪里:
-f
用于代替--file
.--
标记选项的结束,这样即使它以 开头,后面的任何其他参数也不会被视为一个-
。- 我们添加了
/dev/null
至少grep
传递 2 个文件,保证它总是打印文件名。 - 我们使用
*(-.)
所以grep
只看常规的文件。如果不匹配,zsh
将中止不匹配错误并且不运行 grep。
因为,我们传递/dev/null
给grep
,所以我们还可以添加N
glob 限定符 ( *(N-.)
) ,这会导致 glob 在没有匹配项时扩展为空,而不是报告错误,并且grep
只会查看内部/dev/null
(并且默默地失败)。
1 请注意在 shell 语法中引用关键字,例如while
, do
, if
,time
即使部分也会产生影响,因为它会阻止 shell 识别它们;类似地,'v'ar=value
将阻止 shell 将其视为变量赋值,因为'v'ar
它不是有效的变量名称(并且在解析语法后执行引号处理)。或者,如果您编写它们,或者除非您也有这些引用形式的别名(很少有 shell 允许您这样做),则您的foo
别名将不会扩展\foo
f'oo'
-?
²受 Microsoft 启发的实用程序有时会发现明显的例外。
3 对于 GNU 来说grep
,这也适用于其他参数,而不仅仅是第一个参数,因为 GNU grep
(以及现在的一些其他类似 GNU 的实现)即使在非选项参数之后也接受选项。