1.问题背景

作为程序员的我们,在使用Linux或者Git命令时总会想了解某个命令的全部用法,我么一般会在命令末尾加上-h(h全称help)来获得帮助,或者是查看Linux或Git的帮助文档。一般我们-h给出的帮助和帮助文档中的帮助的排版都是这样的。
在这里插入图片描述
在这里插入图片描述
作为Linux和Git初学者的博主我,这么一长串的选项和参数到底怎么用?这些中括号[]和尖括号<>和竖杠|和省略号...到底都是啥意思呀?
这些语法规则难不是问题,最要命的是Linux和Git的官方帮助文档里面从来没有提到过这些语法公式!各类Linux和Git的入门教程+书籍+网上博客教程+大学老师上课课程都不讲解这些语法公式,更变态的是这些教程都会说一句话:“如果想了解某条命令的高级使用,可以参考官方帮助文档”!于是又回到最初的Linux和Git的官方帮助文档,它里面没有提到任何这些语法公式!

作为程序员的我们,每次使用Linux或者Git命令时,肯定想知道每一条命令的具体写法的语法规则,因为一旦我们了解了语法规则,在阅读Linux教程和别人的Linux命令时能更好的理解这些命令。所以我在网上整理出了这篇最全面的Linux系统命令行终端命令语法格式。

首先我们需要知道,任何操作系统Windows,Linux,Mac上的Gitbash的Git命令都是是基于Linux的,所以我们把Linux的系统命令行终端命令语法格式掌握了,在GitBash中使用Git命令和阅读Git命令也会更顺畅,下面我将全面且详细地给予介绍。

2.前言

Linux和Git命令中的中括号[]和尖括号<>和竖杠|和省略号...其实都是根据一个规则制定的,这个规则便是Linux帮助文档的编写规则:命令行界面描述语言Docopt。所有的Linux或Git的帮助文档的公式都是按照命令行界面描述语言Docopt的语法规则来编写,因此我们了解清楚命令行界面描述语言Docopt就终于能读懂Linux和Git命令的帮助文档了!

下面的第3章节3.Linux帮助文档的编写规则:命令行界面描述语言Docopt就是对命令行界面描述语言Docopt的全面解释,其实这部分又臭又长,你可以直接跳过第3章节,直接观看第4章节4.命令的帮助文档-实例解析,遇到不理解的专业词汇再看一看第3章节3.Linux帮助文档的编写规则:命令行界面描述语言Docopt

3.Linux帮助文档的编写规则:命令行界面描述语言Docopt

(1)作用与定义

Docopt可以为命令行应用程序定义接口,并为其自动生成解析器。
Docopt用于描述程序接口的帮助消息和手册页中的约定,比如Linux和Git命令的帮助文档就是按照Docopt编写的。
Docopt中的接口描述就是这样一个帮助文档。我随便编造一个类似于Linux系统的海军的命运系统的帮助文档,来帮助你更好的理解:

Naval Fate.

Usage:
  naval_fate ship new <name>...
  naval_fate ship <name> move <x> <y> [--speed=<kn>]
  naval_fate ship shoot <x> <y>
  naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate -h | --help
  naval_fate --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

中文版的长这样,你应该看得更懂一些。请放心,命令格式都是没有改变的,所以看英文版和看中文版一样。

海军的命运.

用法:
海军的命运 开船 新的<船的名字>...
海军的命运 开船 <船的名字> 移动到 <坐标轴x> <坐标轴y> [--速度=<海里每小时>]
海军的命运 开船 开炮射击 <坐标轴x> <坐标轴y>
海军的命运 水雷 (埋雷|清雷) <坐标轴x> <坐标轴y> [--停泊|--漂泊]
海军的命运 -h | --help
海军的命运 --版本

选项:
-h --help     展示这个帮助页面
--版本     战术“海军的命运”的版本号.
--速度=<海里每小时>  海里每小时 [默认值: 10].
--停泊      停泊船(抛锚固定好船)时,对水雷进行操作.
--漂泊    船在漂泊(开动)时,对水雷进行操作.

由上面的中文版的海军的命运系统的帮助文档,我们可以看出来这是海军对船的多种用法和选项,而Linux和Git命令的帮助消息和开放文档便是海军的命运系统的帮助文档的另一个版本罢了。你现在是不是感觉清晰多了?

该示例描述了可执行的naval_fate接口,它可以通过不同的命令组合(ship、new、move等)、选项(-h、–help、–speed=等)和位置参数(、、)来调用。该示例使用括号“[]”、parens“()”、管道“|”和省略号“…”来描述可选、必需、互斥和重复的元素。这些元素组成了有效的使用模式,每个元素都以程序的名称naval_fate开始。在使用模式下面,有一个带有描述的选项列表。它们描述了一个选项是否有短/长形式(-h,–help),一个选项是否有一个参数(–speed=),以及这个参数是否有一个默认值([default: 10])。docopt实现将提取所有这些信息并生成命令行参数解析器,当使用-h或–help选项调用程序时,界面描述的文本将作为帮助消息显示。

(2)使用模式(使用方法)

发生在关键字使用(不区分大小写)和明显空行之间的文本被解释为使用模式列表。用法之后的第一个单词:被解释为程序的名称。下面是一个不接受命令行参数的程序的最小示例:

my_program

程序可以有几个模式列出与各种元素用来描述模式:

  my_program command --option <argument>
  my_program [<optional-argument>]
  my_program --another-option=<with-argument>
  my_program (--either-that-option | <or-this-argument>)
  my_program <repeating-argument> <repeating-argument>...

下面将描述每个元素和构造。我们将使用单词“word”来描述由空格、“|”字符之一或“…”分隔的字符序列。

(A)参数 (位置参数选项的参数

参数是命令的操作对象,一般文件、目录、用户和进程等可以作为参数被命令操作,用于指定选项操作的位置路径。

  1. 位置参数<argument>ARGUMENT
    以“<”开头、以“>”结尾的单词和大写单词被解释为位置参数,如下面的host和port。
my_program <host> <port>
  1. 选项的参数-o argument--option=argument中的argument
    紧跟在选项后面的参数,用于指定选项的操作对象。

(B)选项 -o--option

选项是包括一个或多个字母的代码,前面有一个“-”或"–"连字符,主要用于改变命令执行动作的类型。
选项又分为短格式选项(-l)和长格式选项(–all)。短格式选项是英文的简写,用一个减号调用,例如ls -a;而长格式选项是英文完整单词,一般用两个减号调用,例如ls --all。

一般情况下,短格式选项是长格式选项的缩写,也就是一个短格式选项会有对应的长格式选项。当然也有例外,比如 ls 命令的短格式选项 -l 就没有对应的长格式选项。所以具体的命令选项可以通过后面我们要学习的帮助命令来进行査询。

选项和参数连用的规则与注意事项

  1. 短选项“-”可以以“堆叠”,意思三个选项-a -b -c可以写成-abc,并且他们作用等价。
  2. 短选项可以在零~多个空格后指定参数,并且他们作用等价。-a file等价于-afile等价于-a(多个空格)file
  3. 短选项堆叠在一个或多空格后指定参数的歧义性:不带空格指定参数的命令-afile存在歧义。因为无法判断-afile是多个堆叠的短选项-a -f -i -l -e,还是选项-a带有参数file。而Linux碰到这种歧义命令的判定方案是:仅当提供了对选项的描述时,这些符号才会被解释为带参数的选项(其实博主也不懂这句话具体啥意思,它的英文原文对这个歧义的解决方案就是这么模糊的描述。所以只能看有没有这种歧义的实例来做测试,才能给出具体的定义)。
  4. 长选项可以在一个或多个空格等于符号=后指定参数:如--input=ARG等价于--input ARG等价于--input(多个空格)ARG
  5. 短选项和长选项在一个或多空格后指定参数的歧义性:-a file--input ARG存在歧义。因为无法判断fileARG分别是短选项-a和长选项--input选项的参数还是位置参数。而Linux碰到这种歧义命令的判定方案是:在使用模式中,只有在提供了该选项的描述时,才会将其解释为选项和选项的参数。否则,它将被解释为选项和位置参数。(其实博主也不懂这句话具体啥意思,它的英文原文对这个歧义的解决方案就是这么模糊的描述。所以只能看有没有这种歧义的实例来做测试,才能给出具体的定义)。
  6. 针对第3点和第5点提到的歧义性,作为程序员的我们,最好的解决方案是:规范书写命令来避免歧义。(1)书写带参数的短选项命令时,最好写成-a(一个或多个空格)file来避免歧义;(2)书写带参数的长选项命令时,最好写成--input=ARG来避免歧义。

(C)命令

所有不遵循上述约定(A)和(B)--options<arguments>的其他单词都被解释为命令或子命令。

(D)[可选元素]

元素指的是:选项,参数,命令。
用方括号“[]”括起来的元素被标记为可选的,意思是:可以有该元素也可以没有该元素。元素是否包含在相同或不同的括号内并不重要,它们完全等价。例如:

my_program [command --option <argument>]

与下面的命令是等价的:

my_program [command] [--option] [<argument>]

因此不要误以为my_program [command --option <argument>]命令只有一下2种可能性:

错误案例:
my_program [command --option <argument>]的所有可能性:
第一种可能性:my_program command --option argument
第二种可能性:my_program

博主我之前就被这里迷惑了,因为我总以为command --option <argument>这3个元素都在一个方括号[]里面,所以博主我错误地理解为:它们应该是要么全部出现,要么全部不出现。正确的情况是这3个元素都是分开的:

正确案例:
my_program [command --option <argument>]的所有可能性:
第一种可能性:my_program command --option argument
第二种可能性:my_program
第三种可能性:my_program command
第四种可能性:my_program --option
第五种可能性:my_program argument
第六种可能性:my_program --option argument
第七种可能性:my_program command argument
第八种可能性:my_program command --option

(E)(必选元素)

默认情况下,所有元素都是必需的,如果不包括在括号“[]”中。然而,有时有必要根据需要显式地使用括号“()”标记元素。例如,当您需要对互斥元素进行分组时(参见下一节):

my_program (--either-this <and-that> | <or-this>)

另一个用例是,当您需要指定如果有一个元素存在,那么就需要另一个元素,您可以这样实现:

my_program [(<one-argument> <another-argument>)]

在这种情况下,有效的程序调用可以没有参数,也可以有两个参数。

(F)元素|其他

互斥的元素可以通过竖杠“|”进行分离,如下:

my_program go (--up | --down | --left | --right)

在需要互斥的情况下,使用括号“()”对元素进行分组。在不需要互斥的情况下,使用括号“[]”将元素分组:

my_program go [--up | --down | --left | --right]

注意,指定几个模式的工作原理与竖杠“|”完全相同,即:

my_program run [--fast]
my_program jump [--high]

与下面的命令等价

my_program (run [--fast] | jump [--high])

(G)元素...

使用省略号“…”指定左边的参数(或一组参数)可以重复一次或多次:

 my_program open <file>...
my_program move (<from> <to>)...

您可以灵活地指定所需的参数数量。这里有3种(冗余的)方法来要求零或多个参数:

my_program [<file>...]
my_program [<file>]...
my_program [<file> [<file> ...]]

一个或多个参数:

my_program <file>...

两个或更多参数:

my_program <file> <file>...

(H)[options]

“[options]”是一个快捷方式,它允许避免在模式中列出所有选项(从带有描述的选项列表中)。例如:

my_program [options] <path>

--all             List everything.
--long            Long output.
--human-readable  Display in human-readable format.

与下面的命令是等价的:

Usage: my_program [--all --long --human-readable] <path>

--all             List everything.
--long            Long output.
--human-readable  Display in human-readable format.

如果您有许多选项,并且所有选项都适用于其中一种模式,那么这将非常有用。或者,如果你有短版本和长版本的选项(在选项描述部分中指定),你可以用一个模式列出其中一个:

Usage: my_program [-alh] <path>

-a, --all             List everything.
-l, --long            Long output.
-h, --human-readable  Display in human-readable format.

(I)[--]

如果不是选项的一部分,则使用双破折号“--”作为分隔选项和位置参数的约定,以便处理可能将文件名误认为选项的情况。为了支持这种约定,在位置参数之前在模式中添加“[--]”。

my_program [options] [--] <file>...

除了这个特殊的含义之外,“--”只是一个普通的命令,所以您可以应用前面描述的任何操作,例如,使它成为required(通过删除括号“[]”)

(J)[-]

当不是选项的一部分时,一个破折号“-”通常用于表示程序应该处理stdin,而不是文件。如果您想遵循这个约定,请将“[-]”添加到您的模式中。"-"本身只是一个普通的命令,你可以用任何意义。

(K)选项描述

选项描述由一列选项组成,这些选项放在使用模式下面。如果在使用模式中没有歧义,可以选择指定它们(在上面的–option部分中描述)。
选项的描述允许指定:

  1. 一些短期和长期选项是同义词
  2. 一个选项有一个参数
  3. 以及一个选项参数的默认值。

规则如下:
以“-”或“–”(不包括空格)开头的每一行都被视为选项描述,例如:

Options:
  --verbose   # GOOD
  -o FILE     # GOOD
Other: --bad  # BAD, line does not start with dash "-"

要指定一个选项有一个参数,请在空格(或=" ="符号)后面放一个描述该参数的单词,如下所示。选项参数遵循<角括号>或大写约定。如果要分隔选项,可以使用逗号。在下面的示例中,这两行都是有效的,但是建议坚持使用单一样式。

-o FILE --output=FILE       # without comma, with "=" sign
-i <file>, --input <file>   # with comma, without "=" sign

使用两个空格来分隔选项和它们的非正式描述。

--verbose MORE text.    # BAD, will be treated as if verbose
                        # option had an argument MORE, so use
                        # 2 spaces instead
-q        Quit.         # GOOD
-o FILE   Output file.  # GOOD
--stdout  Use stdout.   # GOOD, 2 spaces

如果希望为带有参数的选项设置默认值,请将其以[default: ]的形式放入选项的描述中。

--coefficient=K  The K coefficient [default: 2.95]
--output=FILE    Output file [default: test.txt]
--directory=DIR  Some directory [default: ./]

(3)安装并实现Docopt

docopt有多种编程语言。官方实现列在GitHub上的docopt组织中。

4.命令的帮助文档-实例解析

恭喜你,终于看完了,上面所描述的规则就是针对Linux帮助文档和帮助文档的编写者设定的,所以我们站在Linux命令使用者的角度看这些规则可能怪怪的,但是至少咱们也是看得懂命令的定义规则了!下面我将用几份实际的命令帮助文档的实例做一个解析。

(1)Linux的7z压缩命令

7z压缩格式拥有众多优点,具有极高的压缩比率,所以很多开发者会在Linux上安装7z来高效地压缩和解压文件 ,如果你没有安装,你在Linux上编写7z命令是不会被识别的。(如果你想亲自并安装7z,你可以参考这篇文章:linux下安装7z命令及7z命令的使用
在已经安装7z的Linux的终端中输入命令7z --help,我们可以获得7z命令的所有用法的帮助文档:
在这里插入图片描述
注意橙框选中的那一行命令公式,他描述了如何在Linux终端编写7z命令,我们来一一解读一下这个命令公式

7z <command> [<switches>...] <archive_name> [<file_names>...]  [<@listfiles...>]

(1)7z:根据上面3(2)(C)规则的定义,7z没有尖括号和连字符,所以7z就是命令
(2)<command>:根据上面3(2)(C)规则的定义,<command>有尖括号,但<command>在下文的帮助文档中给出了<command>的所有可能性,而这些可能性都是不带连字符的字母,所以<command>不是选项。并且这些有限的可能性不符合位置参数指定命令的操作对象的定义,所以它是命令。又因为<command>跟在7z命令后面,所以<command>子命令
(3)[<switches>...]:根据上面3(2)(D)规则的定义,最外层有方括号[],代表里面的元素可有可没有。而里面是尖括号<>加省略号,意思是switches可以有1个~多个。同时,switches在下文的帮助文档中给出了switches的所有可能性,而这些可能性都是带连字符的字母,所以<switches>选项[<switches>...]代表的是有0~多个<switches>选项
(4)<archive_name>:带有尖括号,说明这个元素是必填的,但在下文的帮助文档中并未给出它的任何定义,所以它不是命令也不是选项。其实<archive_name>代表的意思是被压缩后新生成的压缩包的文件名 或 需要解压的压缩包的文件名,同时它又有尖括号,符合位置参数的定义,所以<archive_name>位置参数
(5)[<file_names>...]:类同于(3)[<switches>...]的结构,代表的是有0~多个<file_names>选项。同时类比于(4)<archive_name><file_names>在下文的帮助文档中并未被给出任何定义,<file_names>代表的意思是需要被压缩的文件的文件名,所以<file_names>也是位置参数
(6)[<@listfiles...>]:类同于(5)[<file_names>...]的结构,<@listfiles...>也是位置参数[<@listfiles...>]代表的是有0~多个<@listfiles...>选项


总结:当我们把上面的结构全部分析完后,我们发现这与Linux系统命令行终端命令语法格式的定义完全一模一样!分析如下:
Linux系统命令行终端命令语法格式:提示符 命令 [ [选项] [选项的参数] ]... [--] [位置参数]...
7z <command>命令[<switches>...]是多个可带可不带参数的选项<archive_name> [<file_names>...] [<@listfiles...>]是多个位置参数

我们再结合一段实际命令进行解析:

7z a -tzip -p111 archive.zip txt.txt

(1)7z:对应的是命令公式的第一个元素7z
(2)a:对应的是命令公式的第二个元素<command>中的子元素a。根据上图文档的解释a: Add files to archive 添加文件到压缩包中,所以a代表这是压缩文件生成压缩包的操作。
(3)-tzip:对应的是命令公式的第三个元素[<switches>...]中的子元素-t{Type},按照Docopt规则,没有{}这种语法,所以我们这里猜测{}代表的是Type选项-t参数。因为选项-t是短选项,选项参数间可以没有空格,那么选项-t后面的zip应该就对应这个Type,也就是选项-t参数。根据上图文档的解释-t{Type}: Set type of archive 设置压缩包的类型,所以-tzip代表是本次压缩生成的压缩包格式是zip
(4)-p111:因为[<switches>...]有省略号,所以<switches>可以有多个,因此-p111命令公式的第三个元素[<switches>...]中的子元素-p{Password}。同理,类比于(3)-tzip选项-p后面的111应该就对应这个Password,也就是选项-p参数。根据上图文档的解释-p{Password}: set Password 设置该压缩包的解压密码,所以-p111代表是解压本次压缩生成的压缩包的密码是111
(5)archive.ziparchive.zip前面没有连字符,所以它是命令公式的第四个元素<archive_name>。这个元素外带尖括号<>,所以它是必填元素。它是必填元素是因为archive.zip用于指定被压缩后新生成的压缩包的文件名 或 需要解压的压缩包的文件名,如果不告诉系统被压缩后新生成的压缩包的文件名 或 需要解压的压缩包的文件名,系统生成压缩包后要给这个压缩包取什么名字呢 或者 系统怎么知道你要解压哪个文件呢?
(6)txt.txt:类同于(5)archive.zip,它是命令公式的第五个元素[<file_names>...],而<file_names>用于指定需要被压缩的文件的文件名
(7)没有了:你可能会想这条命令里面怎么没有与命令公式的第六个元素[<@listfiles...>]相对应的呢?这是因为[<@listfiles...>]外面是方括号[],所以我们可以不用写任何内容来对应[<@listfiles...>]


总结:7z a -tzip -p111 archive.zip txt.txt整条命令的意义就是:将txt.txt文件压缩为archive.zip压缩包,压缩方式为zip,解压密码为111。

5.总结

恭喜你,终于看完了!现在,不管你是在看Linux或Git的帮助文档,总算知道如何看懂那些命令公式了吧~


本文参考文献:
命令行帮助文档语法格式详解

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:1 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐