如何分析命令行参数

Sun, 2006-07-16 01:27 — Marchday

GNU/Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符
。比如有一个命令:

$ myprog -a vv --add -b --file a.txt b.txt - -- -e c.txt

在GNU/Linux系统,对这种情况的一种合理解释是:
a是短选项,带一个参数vv;
add是长选项,无参数;
b是短选项,无参数;
file是长选项,带一个参数a.txt;
b.txt是参数;
-是参数,通常表示标准输入,stdin;
--是一个指示符,表明停止扫描参数,其后所有部分都是参数,而不是选项;
-e是参数;
c.txt是参数

为了简化程序设计,有几个库函数可以优雅地分析命令行参数,原型如下:

#include <unistd.h>

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

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

#define _GNU_SOURCE#include <getopt.h>

int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);

int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);

我们先看看用于分析短参数的getopt函数。参数含义如下:

argc, argv是从main函数获取的参数,原样传给getopt;
optstring指示如何分析参数。

关于optstring,还有几点说明:
如果选项带参数,该选项后接冒号,比如上例中optstring为"a:b",指示a带参数,b没有参数;
如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;
如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回'?',和无法识别的参数返回一样);
如果optstring的开头字符为'+',表明一但遇到一个无选项参数,马上停止扫描,随后的部分当作参数来解释;
如果optstring的开头字符为'-',表明如果遇到无选项参数,则把它当作选项1(不是字符'1')的参数

该函数每解析完一个选项,就返回该选项字符。

如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无参数时,optarg为NULL。

当遇到一个不在optstring指明的选项时,返回字符‘?’。如果在optstring指明某选项带参数而实际没有参数时,返回字符‘?’或者字符‘:’,视optstring的第一个字符而定。这两种情况选项的实际值被保存在optopt中。

当解析错误时,如果opterr为1则自动打印一条错误消息(默认),否则不打印。

当解析完成时,返回-1。

每当解析完一个argv,optind就会递增。如果遇到无选项参数,getopt默认会把该参数调后一位,接着解析下一个参数。如果解析完成后还有无选项的参数,则optind指示的是第一个无选项参数在argv中的索引。

函数getopt_long()的工作方式类似于getopt(),不过它还能接收长选项。在接收长选项之前,我们必须定义个一个结构体数组变量longopts,指明我们希望获取的长选项。

struct option {const char *name;int has_arg;int *flag;int val;};

含义如下:
name指明长选项的名称;
has_arg指明该选项是否带参数,1为是,0为否,2为可选;
flag指明长选项如何返回,如果flag为NULL,则getopt_long返回val。否则返回0,flag指向一个值为val的变量。如果该长选项没有发现,flag保持不变;
val指明返回的值,或者需要加载到被flag所指示的变量中。

option数组的最后一个元素必须全部填充0.

getopt_long的最后一个参数longindex在函数返回时指向被搜索到的选项在longopts数组中的下标。longindex可以为NULL,表明不需要返回这个值。

getopt_long_only类似于getopt_long,但是它把'-'开头的选项当作长选项来处理。如果该选项与长选项不匹配,而与短选项匹配,则可以作为短选项解析。

在短选项找到的时候,getopt_long和getopt_long_only的表现和getopt一样。如果长选项找到了,如果flag为 NULL,返回val,否则返回0。错误情况的处理和getopt一样,只是返回'?'时还可能是别的情况引起的:选项含糊不明确或者无关参数。

我们拿Linux手册的一个例子来说事。

#include <stdio.h> /* for printf */#include <stdlib.h> /* for exit */#include <getopt.h>

intmain (int argc, char **argv) {int c;int digit_optind = 0;

while (1) {int this_option_optind = optind ? optind : 1;int option_index = 0;static struct option long_options[] = {{"add", 1, 0, 0},{"append", 0, 0, 0},{"delete", 1, 0, 0},{"verbose", 0, 0, 0},{"create", 1, 0, ’c’},{"file", 1, 0, 0},{0, 0, 0, 0}};c = getopt_long (argc, argv, "abc:d:012",long_options, &option_index);if (c == -1)break;

switch (c) {case 0:printf ("option %s", long_options[option_index].name);if (optarg)printf (" with arg %s", optarg);

printf ("/n");break;

case ’0’:case ’1’:case ’2’:if (digit_optind != 0 && digit_optind != this_option_optind)printf ("digits occur in two different argv-elements./n");digit_optind = this_option_optind;printf ("option %c/n", c);break;case ’a’:printf ("option a/n");break;

case ’b’:printf ("option b/n");break;

case ’c’:printf ("option c with value ‘%s’/n", optarg);break;

case ’d’:printf ("option d with value ‘%s’/n", optarg);break;

case ’?’:break;

default:printf ("?? getopt returned character code 0%o ??/n", c);}}

if (optind < argc) {printf ("non-option ARGV-elements: ");while (optind < argc)printf ("%s ", argv[optind++]);printf ("/n");}

exit (0);}

我们用digit_optind和this_option_optind来跟踪选项012是否在一起,比如选项 -012 和-0 -1 -2 的optind情况是不一样的,前者返回0、1、2时optind相同,而后者optind的值依次大1。

Comments

SHELL编程如何解析命令行参数

用命令getopt,提供以下代码片段供参考:

#!/bin/sh

while getopts xyz: arguments 2>/dev/null
do
case $arguments in
x) echo "option x";;
y) echo "option y";;
z) echo "option z with arg. $OPTARG";;
/?) echo "Usage: optdemo [-xy] [-z argment]"
exit 1;;
esac
done

echo "/$OPTIND is $OPTIND /$OPTERR is $OPTERR"

getopt();getopt_long();getopt_long_only();option相关推荐

  1. 函数 —— 分析命令行参数 getopt() getopt_long() getopt_long_only()

    为什么需要命令行解析函数? 只按顺序处理参数的话,一些"可选参数"的功能将很难实现. 在Linux中,我们可以使用getopt.getopt_long.getopt_long_on ...

  2. C语言linux getopt_long()函数(命令行解析)(getopt、getopt_long_only)(短选项 -,长选项 --)(option结构体)(optind、optarg变量)

    参考文章:浅谈linux的命令行解析参数之getopt_long函数 文章目录 前言 一.关于命令行参数 二.getopt_long函数 参数以及返回值介绍(以上三个函数都适用): 1.argc和ar ...

  3. linux c 命令行解析函数 getopt getopt_long

    平时在写程序时常常需要对命令行参数进行处理,因为参数少,自己解析就可以搞定:如果命令行个数比较多时,如果按照顺序一个一个定义参数含义很容易造成混乱,而且如果程序只按顺序处理参数的话,一些"可 ...

  4. getopt.h和getopt(),getopt_long()等函数

    下载了一个牛人的代码,里面包括了一个getopt.h的头文件,在vs2008下无法通过编译,没有这个头文件,上网搜索了一些信息,记录下来,以方便以后查阅. getopt.h和对应的链接库不是每个编译器 ...

  5. linux c 命令行解析 getopt getopt_long optarg optind opterr optopt 简介

    目录 getopt 函数 测试代码 getopt_long函数 代码示例 getopt 函数 头文件 #include<unistd.h> 定义函数 int getopt(int argc ...

  6. C getopt.h

    C getopt.h getopt.h getopt函數 getopt_long函數 TensorRT代碼片段 參考連結 getopt.h Gnulib是GNU開源的庫,廣泛用於各種軟體.套件中.ge ...

  7. 命令行解析函数:getopt_long、getopt

    一.前言 在学习一些项目代码时,尤其涉及到命令行传参的代码,经常遇到getopt相关的函数,对这一类函数可以说是既陌生又熟悉.陌生是因为不知道它是干啥的,熟悉呢,是因为经常遇到.于是乎在追踪了多天ip ...

  8. getopt( )和 getopt_long( )

    有关系统调用getopt: 声明:          #include <unistd.h>          int getopt(int argc, char *const argv[ ...

  9. va_list和vsnprintf、getopt

    原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下. VA_LIST的用法:            (1)首先在函数里定义一具VA_LIST型的变 ...

最新文章

  1. oracle 递归查询
  2. XCode4.3.3 + iOS5.1 无证书开发并生成app、ipa文件
  3. c# bitmap 去除噪点_黑头怎么去除最有效用盐处理的方法推荐
  4. Bootstrap4+MySQL前后端综合实训-Day02-AM【Bootstrap4(入门、环境搭建、文字排版、颜色、表格、图片、进度条、折叠、输入框组、模态框)、Font Awesome字体图标】
  5. Dominant Indices(CF 1009 F)
  6. cpu风扇声音大_电脑嗡嗡响,换个大尺寸的CPU风扇,世界一下子安静了
  7. Java系列:《Java核心技术 卷一》学习笔记,chapter11 记录日志
  8. 【~~~】POJ-1006
  9. python设计模式9-装饰器模式
  10. 使用ExchangeRate-API查询免费可用的汇率数据
  11. 遇见未来 | 对话王璞:谈分布式系统在企业落地的挑战
  12. PostgreSql Lock锁
  13. 下载VS2017的网址
  14. 程序员是一群什么样的人,1024程序员节调查报告」这群IT人有点东西哟
  15. 一个人靠不靠谱,在于能力是否配得上承诺
  16. 使用Java API访问HFDS
  17. 国内外遥感类核心期刊汇总
  18. maven 搭建ssm多模块项目(web+service)
  19. Ubuntu 18.04/20.04 多线程下载工具AXEL和AIRA2
  20. 《惢客创业日记》2019.01.21(周一)你还记得米卢吗?

热门文章

  1. angular ng-show ng-hide的兼容性问题
  2. Quartz.net持久化与集群部署开发详解
  3. Ubuntu的which、whereis、locate和find命令
  4. 实现网页中增加刷新按钮、链接的方法 搜集
  5. 表面风平浪静,实则暗流涌动:如何智能发现网络中的异常?
  6. 99%的数据工作者不曾知道的一款利器
  7. android meta data值获取的坑
  8. 使用 Git 改进工作方式
  9. Discuz! X3.2新增管理员无法登录后台的解决办法
  10. 一次expdp 错误的分析处理