现在的位置: 首页 > 综合 > 正文

命令行参数解析(1)

2012年06月30日 ⁄ 综合 ⁄ 共 2999字 ⁄ 字号 评论关闭

 今天在看代码的时候,遇到getopt_long函数,然后查了相关资料,它就是命令行的参数解析.今天就做一些笔记.

Linux下很多程序甚至那些具有图形用户界面(graphical user interface,GUI)的程序,都能接受和处理命令行选项。对于某些程序,这是与其他程序或用户进行交互的主要手段。具有可靠的复杂命令行参数处理 机制,会使得您的应用程序更好、更有用。不过很多开发人员都将其宝贵的时间花在了编写自己的命令行解析器,却不使用 getopt(),而后者是一个专门设计来减轻命令行处理负担的库函数。

1、命令行参数
命令行程序设计的首要任务是解析命令行参数,GUI派的程序员很少关心这个。这里,我们对参数(argument)采用了一种比较通俗的定义:命令行上除命令名之外的字符串。参数由多项构成,项与项之间用空白符彼此隔开。
参数进一步分为选项和操作数。选项用于修改程序的默认行为或为程序提供信息,比较老的约定是以短划线开头。选项后可以跟随一些参数,称为选项参数。剩下的就是操作数了。

2、 POSIX约定POSIX表示可移植操作系统接口:Portable Operating System Interface,电气和电子工程师协会(Institute of Electrical and Electronics Engineers,IEEE)最初开发 POSIX 标准,是为了提高 UNIX 环境下应用程序的可移植性。然而,POSIX 并不局限于 UNIX。许多其它的操作系统,例如 DEC OpenVMS 和 Microsoft Windows NT,都支持 POSIX 标准。

下面是POSIX标准中关于程序名、参数的约定:
程序名不宜少于2个字符且不多于9个字符;
程序名应只包含小写字母和阿拉伯数字;
选项名应该是单字符活单数字,且以短横‘-‘为前綴;
多个不需要选项参数的选项,可以合并。(譬如:foo -a -b -c ---->foo -abc)
选项与其参数之间用空白符隔开;
选项参数不可选。
若选项参数有多值,要将其并未一个字串传进来。譬如:myprog -u "arnold,joe,jane"。这种情况下,需要自己解决这些参数的分离问题。
选项应该在操作数出现之前出现。
特殊参数‘--'指明所有参数都结束了,其后任何参数都认为是操作数。
选项如何排列没有什么关系,但对互相排斥的选项,如果一个选项的操作结果覆盖其他选项的操作结果时,最后一个选项起作用;如果选项重复,则顺序处理。
允许操作数的顺序影响程序行为,但需要作文档说明。
读写指定文件的程序应该将单个参数'-'作为有意义的标准输入或输出来对待。
当然许多标准从恒许未遵守以上约定,主要是历史兼容问题,因为标准出现之前,就已经存在N多程序了。

3、GNU长选项
GNU鼓励程序员使用--help、--verbose等形式的长选项。这些选项不仅不与POSIX约定冲突,而且容易记忆,另外也提供了在所有GNU工具之间保持一致性的机会。GNU长选项有自己的约定:
对于已经遵循POSIX约定的GNU程序,每个短选项都有一个对应的长选项。
额外针对GNU的长选项不需要对应的短选项,仅仅推荐要有。
长选项可以缩写成保持惟一性的最短的字串。
选项参数与长选项之间或通过空白字符活通过一个'='来分隔。
选项参数是可选的(只对短选项有效)。
长选项允许以一个短横线为前缀。

4、基本的命令行处理技术
C程序通过argc和argv参数访问它的命令行参数。argc是整型数,表示参数的个数(包括命令名)。main()函数的定义方式有两种,区别仅在于argv如何定义:

  1. int main(int argc ,char** argv)
  2. {
  3. .....
  4.  return 0;
  5. }
  6. int main(int argc, char* argv[])
  7. {
  8. .....
  9.  return 0;
  10. }

当 C 运行时库的程序启动代码调用您的 main() 时,已经对命令行进行了处理。argc 参数包含参数的计数值,而 argv 包含指向这些参数的指针数组。argv[0]是程序名。

5、命令行参数解析函数 —— getopt()

getopt()函数声明如下:#include <unistd.h>

int getopt(int argc, char * const argv[], const char *optstring);

extern char *optarg;
extern int optind, opterr, optopt;

该函数的argc和argv参数通常直接从main()的参数直接传递而来。optstring是选项字母组成的字串。如果该字串里的任一字符后面有冒号,那么这个选项就要求有选项参数。

当 给定getopt()命令参数的数量 (argc)、指向这些参数的数组 (argv) 和选项字串 (optstring) 后,getopt() 将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有可识别的选项,将返回 -1,此任务就完成了。

getopt() 所设置的全局变量包括:
char *optarg——当前选项参数字串(如果有)。
int optind——argv的当前索引值。当getopt()在while循环中使用时,循环结束后,剩下的字串视为操作数,在argv[optind]至argv[argc-1]中可以找到。
int opterr——这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。
int optopt——当发现无效选项字符之时,getopt()函数或返回'?'字符,或返回':'字符,并且optopt包含了所发现的无效选项字符。

下面就用getopt()来写个小程序,体验一下命令行解析的快乐。

程序描述:

程序名:opt_parse_demo

选项:
-n —— 显示我的名字。
-g —— 显示我女朋友的名字。
-l —— 带参数的选项.

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main (int argc, char **argv)
  4. {
  5. int oc; /*选项字符 */
  6. char *b_opt_arg; /*选项参数字串 */
  7. while((oc = getopt(argc, argv, "ngl:")) != -1)
  8. {
  9. switch(oc)
  10. {
  11. case 'n':
  12. printf("My name is Lyong./n");
  13. break;
  14. case 'g':
  15. printf("Her name is Xxiong./n");
  16. break;
  17. case 'l':
  18. b_opt_arg = optarg;
  19. printf("Our love is %s/n", optarg);
  20. break;
  21. }
  22. }
  23. return 0;
  24. }
  25. 运行结果:$ ./opt_parse_demo -n
  26. My name is Lyong.
  27. $ ./opt_parse_demo -g
  28. Her name is Xxiong.
  29. $ ./opt_parse_demo -l forever
  30. Our love is forever
  31. $ ./opt_parse_demo -ngl forever
  32. My name is Lyong.
  33. Her name is Xxiong.
  34. Our love is forever

接下来一篇将会接着介绍getopt_long等函数的运用和实例.

~~END~~

抱歉!评论已关闭.