⚠️重要

⚠️重要

我见过--compgen命令中使用过。

例如:

compgen -W "foo bar baz" -- b

--里面的那个是什么意思?

答案1

--更准确地说,大多数 Bash 中都使用双破折号 ( )内置命令和许多其他命令来表示命令选项的结束,之后仅接受位置参数。

使用示例:假设您要在文件中查找字符串-v。通常-v会被认为是反转匹配含义的选项(仅显示不匹配的行),但您可以像这样--grep 查找字符串:-v

grep -- -v file

答案2

man bash我们可以读入Shell 内置命令部分 (在线文档):

除非另有说明,本节中记录的每个内置命令都以接受选项-开头-- 表示选项的结束

:truefalse和内置函数test不接受选项并且不进行--特殊处理。exitlogoutbreakcontinuelet和内置函数shift接受并处理以 开头的参数,-而不需要--。其他接受参数但未指定为接受选项的内置函数会将以 开头的参数解释为-无效选项,并需要--阻止这种解释。

请注意,这echo并不--意味着选项结束。

答案3

这标志着参数(选项)列表的结束。

答案4

在使用的命令中POSIXgetopt()用于解析选项的 API 以及其他几个选项--标志着选项的结束。

在:

rm -f -- -f

第一个-f被视为 的选项rm,而第二个被视为要删除的文件的名称,因为过去的所有内容--都不被视为选项。

在符合 POSIX 的实用程序和getopt()实现中,在非选项参数之后不接受选项,因此例如:

grep pattern -f

需要pattern在名为 的文件中查找匹配的行-f

然而,大多数 GNU 实用程序(包括 GNU)所使用的GNU 实现getopt()及其扩展(但不是它的任何内置函数,即使是 GNU shell)默认情况下不会这样做,除非环境中有变量。getopt_long()grepbashbashPOSIXLY_CORRECT

因此,对于这些,--即使有主要的非选项参数,也是需要的:

grep -- pattern -f

标记选项结束的一种较旧方法是使用-。您会发现大多数实现以及 ksh 或 zsh 的大多数内置函数sh仍然支持作为选项结束标记。-然而,如今这种情况并不常见。

已知某些命令不支持--选项标记的结尾。大多数echo实现都属于其中。那是它们不能用于输出任意数据的原因之一

⚠️重要

--当非选项参数以-(或可能+对于某些命令)开头时,这是需要的,但是另外,当您不能保证某些非选项参数不会以-/开头时+。包括了:

  • rm -f -- "$file"
  • rm -f -- "${files[@]}"
  • rm -f -- *.txt
  • rm -f -- $(command-that-generates-a-list-of-files-or-file-patterns)
  • cmd | xargs rm -f --

如果您不能保证命令支持--作为选项标记的结尾,对于那些文件名参数,另一种方法是在文件名前面加上前缀./

somegrep pattern ./*.txt

未能添加这些--可能会引入任意命令注入漏洞,特别是如果你也忘记引用你的扩展。例如:

sed -e 's/foo/bar/' *.txt

如果当前工作目录中reboot有一个文件被调用,则将运行。'-es/.*/reboot/e;#.txt'通过将其更改为sed -e 's/foo/bar/' -- *.txt或来修复sed -e 's/foo/bar/' ./*.txt

同样适用于:

rename 's/foo/bar/' *foo*

有一些rename变体;请注意某些(不易受攻击的)rename变体不支持--.

print $var

zsh(即使在该 shell 中不带引号的参数扩展相对安全),如果$var包含,将运行重新启动-va[1$(reboot)]。修复了print -- $varprint - $var尽管您可能还想print -r -- $var禁用反斜杠处理。

相关内容