我见过--
在compgen
命令中使用过。
例如:
compgen -W "foo bar baz" -- b
--
里面的那个是什么意思?
答案1
--
更准确地说,大多数 Bash 中都使用双破折号 ( )内置命令和许多其他命令来表示命令选项的结束,之后仅接受位置参数。
使用示例:假设您要在文件中查找字符串-v
。通常-v
会被认为是反转匹配含义的选项(仅显示不匹配的行),但您可以像这样--
grep 查找字符串:-v
grep -- -v file
答案2
man bash
我们可以读入Shell 内置命令部分 (在线文档):
除非另有说明,本节中记录的每个内置命令都以接受选项
-
开头--
表示选项的结束。
:
、true
、false
和内置函数test
不接受选项并且不进行--
特殊处理。exit
、logout
、break
、continue
、let
和内置函数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()
grep
bash
bash
POSIXLY_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 -- $var
或print - $var
尽管您可能还想print -r -- $var
禁用反斜杠处理。