短/长选项与选项参数 - 这是一种惯例吗?

25

看起来大多数命令都使用这样的选项参数:

  1. 如果一个短选项需要一个选项参数,该选项与选项参数之间用空格分隔,例如:

    $ head -n 10
    
    如果一个长选项需要一个选项参数,则该选项与选项参数之间用 = 分隔,例如:
  2. $ head --lines=10
    
    这是一种约定吗?如果是,我在哪里可以找到它?此外,背后的逻辑是什么?

    为什么它不是

        $ head --lines 10
    

    ?


5
许多需要长选项的命令都将等号视为可选项,例如GNU的headgrep。从man getopt_long中可以看到:“长选项可能需要参数,格式为--arg=param或--arg param。”但是各个实用程序的man页面通常不会记录等号是可选的。 - Dennis Williamson
1
在长选项参数之前使用等号是必须的,如果该参数本身是可选的并且具有默认值(如果未指定)。考虑ls --color,默认为alw[ays]。在该示例中省略等号将导致输入被视为命令的文件或目录。 - user4104817
1
@Chinggis6:这取决于实用程序和选项。你的ls示例需要等号,但考虑:echo foo | grep --regexp o - 它可以带或不带等号工作,--max-count也是如此。然而,grep --color需要等号! - Dennis Williamson
1个回答

40

短选项的基本原理在 POSIX 实用约定 中有详细记录。由于广泛的历史先例,大多数选项解析器允许将值“附加”到字母上(例如 -n10)。

长选项的基本原理由 GNU 在其编码标准getopt_long() 的手册页面中指定。


很久很久以前,在一个很久很久以前的StackOverflow上,有一个关于命令选项样式的问题。也许不是一个好问题,但我认为回答拯救了它(但我承认有偏见)。无论如何,它已经被删除了,所以我要在这里恢复我的答案,因为(a)重新发现答案是一个痛苦的过程,(b)它包含与选项相关的有用信息。
你认识多少种不同类型的选项?我可以想到很多,包括:
  • 单个字母选项以单破折号为前缀,当没有参数时可以分组,参数可以附加到选项字母或下一个参数中(许多Unix命令;大多数POSIX命令)。
  • 单个字母选项以单破折号为前缀,不允许分组,必须附加参数(RCS)。
  • 单个字母选项以单破折号为前缀,不允许分组,参数必须是分开的(pre-POSIX SCCS,如果我没记错的话)。
  • 多个字母选项以单破折号为前缀,参数可以附加或在下一个参数中(X11程序)。
  • 多个字母选项以单破折号为前缀,可以缩写(Atria Clearcase)。
  • 多个字母选项以单加号为前缀(已过时)。
  • 多个字母选项以双破折号为前缀;参数可以跟随 '=' 或分开(GNU实用程序)。
  • 没有前缀/后缀的选项,一些名称具有缩写或被暗示,参数必须是分开的。(AmigaOS Shell,由porneL添加)

有些选项需要一个可选参数,有时必须附加,有时必须跟随 '=' 符号。 POSIX 对可选参数的支持不太明显(POSIX getopt() 仅允许它们出现在命令行上的最后一个选项中)。

所有合理的选项系统都使用只包含双破折号 ('--') 的选项来表示“选项结束”,接下来的参数是“非选项参数”(通常是文件名),即使它们以破折号开头。(我认为支持这种表示法是必要的。)请注意,如果您有一个带有期望参数的选项 '-f' 的命令 'cmd',那么如果您用 '--' 替换参数调用它('cmd -f -- -other'),许多版本的 getopt() 将把 '--' 视为 '-f' 的文件名,然后将 '-other' 解析为常规选项。也就是说,如果必须将其解释为另一个选项的参数,则 '--' 不会终止选项。

许多但不是所有程序都接受单破折号作为文件名,表示标准输入(通常)或标准输出(偶尔)。有时,如 GNU 'tar',两者可以在单个命令行中使用:

tar -cf - -F - | ...

第一个单独的短横线表示“写入标准输出”; 第二个表示“从标准输入读取文件名”。
一些程序使用其他约定 - 即,不以短横线为前缀的选项。其中许多来自Unix最古老的日子。例如,“tar”和“ar”都接受没有短横线的选项,因此:
tar cvzf /tmp/somefile.tgz some/directory

dd 命令完全使用 opt=value

dd if=/some/file of=/another/file bs=16k count=200

一些程序允许您完全交错选项和其他参数;例如,不带POSIXLY_CORRECT的环境下运行的C编译器、make和GNU实用程序。许多程序期望选项在其他参数之前。
现代程序(如git)越来越倾向于使用基本命令名称(git),后跟子命令(commit),再后跟选项(-m“提交消息”)。这种风格最初由sccs界面到SCCS命令,然后是cvssvn也使用它(它们都是版本控制系统)。但是,其他大型命令套件在适当时也会采用类似的风格。
我对不同系统没有强烈的偏好。当选项较少时,具有助记价值的单个字母很方便。GNU支持此功能,但建议在双破折号之前使用多字母选项作为备选。
我反对的事情有一些。最糟糕的之一是使用相同的选项字母,根据先前使用的其他选项字母,其含义不同。在我的书中,这是一个禁忌,但我知道有一些软件这样做。
另一个令人反感的行为是处理参数的风格不一致(特别是对于单个程序,但也适用于一套程序)。要么需要附加参数,要么需要分离参数(或允许两者),但不要使某些选项需要附加参数,而其他选项需要分离参数。并且要对是否可以使用“=”来分隔选项和参数保持一致。
与许多(与软件相关的)事物一样,一致性比个体决策更重要。
无论你做什么,请务必阅读TAOUP的命令行选项并考虑命令行界面标准。(由J F Sebastian添加-谢谢;我同意。)

5
+1哇!这个回答提供了我梦寐以求的一切!感谢你所投入的时间和精力! - helpermethod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接