是否有一个适当的定义方法来分隔C中的命令参数?

时间:2015-06-04 14:44:40

标签: c linux arguments argv argc

例如,考虑一下这个电话:

>routine -h -s name -t "name also" -u 'name as well'

这会返回8个参数还是更多?是否有一个定义的标准,如何解析它们?这会在哪里?

注意:我对代码不感兴趣,但适用的规则或标准。我不认为在某处读取源代码作为标准的文档,我认为它必须驻留在某处。

3 个答案:

答案 0 :(得分:1)

正在使用的shell负责解析命令行并适当地调用exec*()。请参阅相关shell的文档以了解其规则,并查看其源代码以了解它如何解析命令行。

答案 1 :(得分:1)

标准命令shell是一种编程语言,其操作(主要)调用"实用程序",它们是可执行程序。 shell执行的工作是设置标准环境以调用该实用程序,其中包括:

  • 确定哪个可执行文件对应于要调用的实用程序;

  • 将实用程序的stdin,stdout和stderr文件描述符分配给适当的流;

  • 创建argv参数向量并将其传递给调用的实用程序;

  • 设置实用程序的environ全局,实用程序可以通过getenv标准库函数访问该实用程序;

与任何编程语言一样,shell具有值,文字,变量和控制流。它有一个语法(以及一个非常特殊的词法分析算法)。它还有其他原语,专门为其任务而设计。

例如,/usr/bin"this is not a sentence"是shell语言中的文字值。围绕其中第二个的报价不是价值的一部分;它们是文字字符串的语言语法的一部分。 (shell语言允许在没有引号的情况下编写许多文字字符串,并且还包括复杂的表达式语言,因此并非所有双引号字符串都是文字,但在简单的情况下,引用的字符串在概念上与C中的引用字符串不同。 。)

基本语法和语义由Posix标准化。许多常用的shell语言大多符合此标准。几乎所有都提供扩展;除非启用特定选项,否则某些(如果不是大多数)甚至与基本标准也不完全兼容。 (例如,对于bash,使用--posix命令行参数调用它。)但是,通常遵循基本原则,并且阅读上面的Posix链接将提供良好的概述。它包括完整的语法。

一般来说,程序如下:

  • shell将命令行分成"单词"。
  • 有些词是"扩展"可能被零或多个词取代。
  • 有些单词被解释为文件描述符重定向;其他人作为环境变量分配。
  • 如果结果是特定的shell语法,则执行该语法。否则,第一个单词将被解释为shell函数的名称,内置命令或外部实用程序
  • 如果命令解析为外部实用程序,则命令行中的单词(已经用作重定向和赋值的单词除外)将放入argv向量中,并调用该实用程序。

它比这复杂得多,但这是基本模型。

使用exec*系列标准库函数执行调用该实用程序,该函数作为参数:

  • 可执行文件的路径
  • 指向字符串的指针的零终止向量,它将是argv向量
  • 指向name=value形式字符串的指针的零终止向量,该字符串将是environ全局字符串。

exec调用然后调用外部实用程序。它将参数向量和环境列表复制到实用程序的地址空间中,但除了检查两个列表的总大小是否超过某个系统限制之外,不会修改或验证这些值。

本答案的其余部分涉及实用程序本身(可能或应该)如何解析它接收的参数向量。

没有解释命令行参数的标准,但是有指导方针,并且存在标准(并且不是那么标准)的库例程,它们强加了一种事实上的标准,它定义了用户(可能)期望的内容。

首先,Posix guidelines(主要)由Posix标准getopt函数实现。这些指南建议可选参数(带有-标志的参数)位于所有位置参数之前。

然而,并非所有Posix实用程序都符合这些建议,并且常见的是找到" permute"参数,允许选项遵循位置参数。这个机制(大部分)是由getopt的Gnu版本实现的。此外,Gnu定义(并建议使用)getopt_long函数,该函数允许使用--启动多字符选项。

在所有情况下,解析可选标志参数的方式取决于该选项是否定义为接受参数。所以

-s1 word

可以解析为:

  • 如果-s接受论证:
    • 选项-s,带参数" 1"
    • 位置参数"字"
  • 如果-s没有参数,-1是一个没有参数的有效标志
    • 选项-s
    • 选项-1
    • 位置参数"字"
  • 如果-s没有参数,-1确实会参与争论:
    • 选项-s
    • 选项-1,带参数" word"

除了上述内容之外,还有一些命令接受"长选项"以单个破折号开始(因此不允许将短选项压缩成单个单词)。这是TCL使用的样式,后面跟着许多GUI命令。可以使用GNU函数getopt_long_only解析此样式(请参阅上一个链接)。

答案 2 :(得分:0)

POSIX定义getopt()函数和getopts命令(通常内置在shell中)来解析命令行参数。

标准只允许使用单字母选项名称,因此它不支持您的示例:

routine -h -s1 name -s2 "name also" -s3 "name as well"

注意:在您的问题中,您在命令行末尾有"name as well'。在routine甚至看到它的参数之前,shell会拒绝这一点,因为引号不匹配。我认为这只是一个错字。

命令支持扩展选项语法很常见。例如,除了标准的单字母选项之外,GNU工具通常支持由--而不是-引入的选项的长名称。 getopt函数is documented here的GNU版本。