加载中...
不想等待可以点我关掉

以下内容由Deepseek生成,仅作记录

命令行工具的选项(options,也叫“开关”或“标志”)解析有很多约定。POSIX 标准定义了一套“短选项”的语法规范,GNU 项目在此基础上增加了“长选项”等扩展。日常使用的大部分 Linux/Unix 命令都遵循或部分遵循这些惯例。


1. POSIX 短选项惯例

POSIX(Portable Operating System Interface)在《Utility Syntax Guidelines》中定义了命令行工具应遵循的基本语法。

1.1 短选项以单个连字符开头

短选项通常是一个连字符 - 后跟一个字符,例如:

1
2
3
ls -a
grep -i
sort -r

选项名一般是字母或数字。

1.2 无参数短选项可以合并

多个不带参数的选项可以写在一起,只用一个连字符:

1
2
3
ls -la
# 等价于
ls -l -a

但若某个选项需要参数,合并时它会“吞掉”后面的内容作为参数:

1
grep -in pattern file

这里的 -in 被解释为 -i -n,因为 -i-n 都不需要参数。如果写成:

1
grep -on pattern file

-o 需要参数吗?grep -o 确实不需要。但假设某个工具 foo -o 需要参数,那么:

1
foo -obar

通常表示选项 -o,其参数是 bar,而不是 -o -b -a -r

1.3 选项参数的形式

如果短选项需要参数,参数可以:

  • 作为同一个单词中选项后面的部分:
1
foo -ofilename
  • 或者作为下一个独立的单词:
1
foo -o filename

两种形式都符合 POSIX 惯例。但可选参数(optional option argument)通常要求参数紧跟在选项后,避免歧义:

1
foo -oARG   # 可选参数应这样写

1.4 选项必须出现在操作数之前

POSIX 规定,选项解析遇到第一个非选项参数(操作数)时停止,后面的内容都视为操作数,即使它们以 - 开头:

1
command -a arg1 -b

这里的 -b 会被当作普通操作数,而不是选项,因为它在 arg1 之后。若要改变这种严格顺序,需要 GNU 扩展或特定工具支持。

1.5 -- 终止选项解析

-- 是一个特殊标记,表示“选项到此结束”,后面的所有内容都作为操作数处理,即使以 - 开头:

1
2
rm -- -filename
touch -- --weird-name

1.6 单个 - 作为标准输入/输出占位符

很多命令将单独一个 - 作为操作数,表示标准输入或标准输出:

1
2
cat file -    # 先输出 file 内容,再输出标准输入
tar cf - . # 将归档写到标准输出

注意:- 本身通常不作为选项名。


2. GNU 扩展:长选项

GNU 项目在保留 POSIX 短选项的基础上,增加了“长选项”,提高了可读性。

2.1 长选项以两个连字符开头

1
2
3
ls --all
grep --ignore-case
sort --reverse

长选项由字母、数字和连字符组成,通常是一个或多个完整单词。

2.2 长选项参数

带参数的长选项有两种写法:

  • 用等号连接:
1
grep --after-context=5
  • 用空格分隔:
1
grep --after-context 5

两种形式通常都支持。

若长选项有可选参数,应使用等号形式:

1
2
command --color=auto
command --color

2.3 长选项的缩写

GNU getopt_long 允许长选项缩写,只要缩写是唯一的。例如:

1
2
ls --all
ls --al

如果 --all 是唯一匹配的,--al 可以缩写。但脚本中应尽量使用完整长选项,避免新增选项导致歧义。

2.4 常用 GNU 标准长选项

GNU 建议所有工具支持:

  • --help:显示帮助信息
  • --version:显示版本信息

这是 GNU 编码规范的一部分。


3. POSIX 与 GNU 选项解析的差异

3.1 选项和操作数的顺序

  • POSIX:选项解析在第一个非选项操作数后停止。
  • GNU:默认情况下,getopt_long 会“排列”参数,将选项移到操作数前面继续解析,除非设置了环境变量 POSIXLY_CORRECT

示例:

1
mycmd arg1 -a
  • POSIX 模式:-a 被当作操作数。
  • GNU 模式:-a 被识别为选项,arg1 最终作为操作数。

GNU 这样做是为了方便用户将选项写在后面,但会打破严格的 POSIX 兼容性。

3.2 长选项

POSIX 不定义长选项。长选项是 GNU 扩展,后来被许多非 GNU 工具接受,但严格 POSIX 环境可能不支持。


4. 命令行选项设计建议

如果你要编写命令行工具,遵循以下约定可以提高一致性和可用性:

  1. 短选项用于常用操作,长选项用于可读性。

    1
    2
    3
    -h, --help
    -v, --version
    -f, --file=FILE
  2. 无参数选项可以合并,有参数选项尽量使用独立参数或等号。
    避免可选参数,容易造成歧义。

  3. 始终支持 -- 结束选项解析。
    这样用户可以处理以 - 开头的文件名。

  4. 选项在操作数之前。
    除非刻意支持 GNU 排列,否则保持传统顺序。

  5. 使用 --help--version
    这是 GNU 标准,用户已经习惯。

  6. 选项名避免使用数字开头,防止与操作数混淆。
    POSIX 允许数字,但可读性差。

  7. 如果需要多个参数,优先用逗号分隔或多次指定选项。
    POSIX 惯例是一个选项最多一个参数。


5. 示例

一个兼容 GNU/POSIX 风格的工具调用可能长这样:

1
mytool --verbose --output=result.txt -- input.txt
  • --verbose:长选项,无参数
  • --output=result.txt:长选项带参数
  • --:结束选项
  • input.txt:操作数,即使名字像选项也不解析

等价的短选项形式:

1
mytool -v -o result.txt -- input.txt

或合并无参数短选项:

1
mytool -v -o result.txt -- input.txt

总结:POSIX 定义了短选项的基本规则,GNU 扩展了长选项和更宽松的参数排列。现代 Linux 工具大多结合两者,遵循“短选项易用、长选项可读”的原则。