仅用引号包围选项值与用引号包围选项名称和选项值之间有什么区别?

仅用引号包围选项值与用引号包围选项名称和选项值之间有什么区别?

有什么区别

  • 引号仅包围选项值

    例如:grep --file="grep pattern file.txt" *

  • 选项名称和选项值用引号括起来

    例如:grep "--file=grep pattern file.txt" *

它们产生相同的结果。

答案1

shell 中的引号和反斜杠用于消除某些字符的特殊性,以便将它们视为普通字符。

双引号的特殊之处在于它们仍然允许在其中进行扩展。或者换句话说,在它们之中$\、 和`仍然是特殊的。它们还会影响这些扩展的执行方式。

在该行中,shell 唯一的特殊字符是:

  • 空格,在 shell 的语法中(就像在许多语言中一样)用于分隔语法中的单词,特别是对于该行,参数简单的命令(这是 shell 知道的几个结构之一,也是主要结构)。
  • 末尾的换行符(除其他外)用于分隔命令
  • *,这是一个全局模式运算符,并且这样一个字符的存在,当不在简单的命令行中引用时,会触发一种称为文件名生成或者通配或者路径名扩展(POSIX 措辞)。

其他字符在 shell 语法中没有特殊意义。

在这里,我们想要做的是让 shell 使用/usr/bin/grep这些参数执行该文件:

  1. grep
  2. --file=grep pattern file.txt
  3. 以及以下内容:当前工作目录中的文件列表。

所以我们确实想要:

  • 空间被视为这些之间的单词分隔符
  • 新队界定该命令
  • *被视为全局运算符并扩展到当前工作目录中的非隐藏文件。

所以上面的那些字符一定不能被引用。

然而,其中有两个空间我们希望包含在传递给 的第二个参数中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/nullgrep,所以我们还可以添加Nglob 限定符 ( *(N-.)) ,这会导致 glob 在没有匹配项时扩展为空,而不是报告错误,并且grep只会查看内部/dev/null(并且默默地失败)。


1 请注意在 shell 语法中引用关键字,例如while, do, if,time即使部分也会产生影响,因为它会阻止 shell 识别它们;类似地,'v'ar=value将阻止 shell 将其视为变量赋值,因为'v'ar它不是有效的变量名称(并且在解析语法后执行引号处理)。或者,如果您编写它们,或者除非您也有这些引用形式的别名(很少有 shell 允许您这样做),则您的foo别名将不会扩展\foof'oo'

-?²受 Microsoft 启发的实用程序有时会发现明显的例外。

3 对于 GNU 来说grep,这也适用于其他参数,而不仅仅是第一个参数,因为 GNU grep(以及现在的一些其他类似 GNU 的实现)即使在非选项参数之后也接受选项。

相关内容