命令行参数顺序

6 command-line arguments

有人曾经告诉我,在解析命令行上的选项时有一个标准。就像是:

./script.sh [options/flags] [command or file]
Run Code Online (Sandbox Code Playgroud)

我知道在解析 shell 脚本时这会让生活更轻松,因为您可以shift通过标志并且可以访问任何剩余的东西$@ or $*,但是是否有实际的书面标准?

我看大多数程序遵循这个标准,但也有一些例外,例如,ls其中ls -l /pathls /path -lls /path -l /path2都是可以接受的。

Kus*_*nda 8

POSIX 基本定义有一节关于“实用程序约定”,它适用于 POSIX 基本实用程序。

在解析 shell 脚本或 C 程序中的命令行时,标准getopts实用程序和getopt()系统接口(“C 函数”)遵循准则(在上面链接的页面上的进一步下方)。具体来说,对于getopts(例如):

当遇到选项结束时,getopts实用程序应以大于零的返回值退出;shell 变量OPTIND应设置为第一个操作数的索引,"$#" +1如果没有操作数,则为该值;该name变量应设置为的字符。以下任何一项都应标识选项的结束:第一个--不是选项参数的参数,找到不是选项参数且不以 a 开头的参数-,或遇到错误。

这基本上是说选项应该先出现,然后是操作数(你的“命令或文件”)。

以任何其他方式执行它都会导致使用getoptsgetopt()不可能,并且还可能使习惯于为命令指定选项和操作数的 POSIX 方式的用户感到困惑。

请注意,上述标准仅适用于 POSIX 实用程序,但因此它通常为 Unix 实用程序设置了优先级。显然,非标准 Unix 实用程序可以选择遵循或打破这一点。

例如,GNU coreutils,即使它们实现了标准实用程序,也允许诸如

$ ls Documents/ -l
Run Code Online (Sandbox Code Playgroud)

如果POSIXLY_CORRECT未设置环境变量,而相同实用程序的 BSD 版本则没有。

这导致以下在 BSD 系统上按预期工作(如果您期望 POSIX 行为,即):

$ touch -- 'test' '-l'

$ ls -l test -l
-rw-r--r--  1 kk  kk  0 Jan 11 16:44 -l  
-rw-r--r--  1 kk  kk  0 Jan 11 16:44 test
Run Code Online (Sandbox Code Playgroud)

但是在 GNU coreutils 系统上,你会得到

$ ls -l test -l
-rw-r--r-- 1 kk kk 0 Jan 11 16:44 test
Run Code Online (Sandbox Code Playgroud)

然而:

$ env POSIXLY_CORRECT=1 ls -l test -l
Run Code Online (Sandbox Code Playgroud)

$ ls -l -- test -l
Run Code Online (Sandbox Code Playgroud)

也会在 GNU 系统上做“正确”的事情。