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> int
main (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的更多相关文章

  1. 【C】命令行参数解析——getopt、getopt_long及getopt_long_only

    前言 在linux下学习开源代码Webbench,遇到get_long等函数的用法,一时有点懵,故想深入了解这类命令行解析函数,并记此博文. 1.getopt getopt主要用来处理短命令行选项,例 ...

  2. getopt、getopt_long和getopt_long_only解析命令行参数

    一:posix约定: 下面是POSIX标准中关于程序名.参数的约定: 程序名不宜少于2个字符且不多于9个字符: 程序名应只包含小写字母和阿拉伯数字: 选项名应该是单字符或单数字,且以短横 '-' 为前 ...

  3. getopt getopt_long

    getopt_long支持长选项的命令行解析,使用man getopt_long,得到其声明如下: #include <getopt.h> int getopt_long(int argc ...

  4. 函数参数选项的处理getopt getopt_long getopt_long_only

    转载:http://blog.chinaunix.net/uid-20321537-id-1966849.html   在头文件中int getopt(int argc,char *argv[], c ...

  5. Use getopt() & getopt_long() to Parse Arguments

    Today I came across a function [getopt] by accident. It is very useful to parse command-line argumen ...

  6. 命令行参数解析:getopt,getopt_long

    #include <unistd.h> int getopt(int argc, char * const argv[], const char *optstring); extern c ...

  7. getopt() getopt_long()函数手册[中文翻译]

    getopt()函数 getopt_long函数 函数原型(function prototype) #include <unistd.h> int getopt(int argc, cha ...

  8. apue编程之getopt ,getopt_long使用方法以及实例

    1.getopt 1.1 函数定义 int getopt(int argc, char * const argv[], const char *optstring);#include <unis ...

  9. C语言命令行解析函数:getopt/getopt_long

    命令行工具下的参数选项有两种,长选项和短选项.短选项以-开头,后面跟单个字母:长选项以--开头,后面可跟多个字母. 一. getopt() 1.功能:解析命令行短选项参数 2.函数原型: #inclu ...

随机推荐

  1. Spark学习体系

    底理解Spark,能够分为以下几个层次. 1 Spark基础篇 1.1 Spark生态和安装部署 在安装过程中,理解其基本操作步骤. 安装部署 Spark安装简单介绍 Spark的源代码编译 Spar ...

  2. MYSQL大小写(由于数据由windows迁移到Linux导致)

    今日从sqlserver上迁移了一个数据库到Linux的MySQL中,迁移成功了,但是应用却跑不通,查看日志发现,提示找不到表,我注意到,表名都是存在大小写的,而MySQL中的表名都是小写的.这提醒了 ...

  3. linux驱动: 如何向模块传递参数, module_param和module_param_array

    如何向模块传递参数,Linux kernel 提供了一个简单的框架.    1.  module_param(name, type, perm); name 既是用户看到的参数名,又是模块内接受参数的 ...

  4. HDU 2023题解分析

    我想说这道题我还没弄明白我错哪了,交了20多遍一直都是Runtime Error,改了N次还是不对,后来搜了一下,说是数组开小了,又把数组开大,还不对,又改发现一个平均值求错,再改,还不对,洗洗睡吧. ...

  5. Nginx 之二: nginx.conf 配置及基本优化

    一:常用功能优化: 1:网络连接的优化: 只能在events模块设置,用于防止在同一一个时刻只有一个请求的情况下,出现多个睡眠进程会被唤醒但只能有一个进程可获得请求的尴尬,如果不优化,在多进程的ngi ...

  6. NSString 用法大全。

    一.NSString 创建字符串.  NSString *astring = @"This is a String!"; 创建空字符串,给予赋值.  NSString *astri ...

  7. (IOS)多线程开发

    一.线程的使用 以向网络请求一张图片为例 -(void)downURL:(NSURL *)aURL { NSData *d = [NSData dataWithContentsOfURL:aURL]; ...

  8. ASP.NET JQuery 随笔-搜索框默认提示

    一.文本框中创建默认文本提示 通常用户在搜索内容时,在文本框输入内容前,文本框都会给出默认提示,提示用户输入正确的内容进行搜索. 当文本框获得焦点,如果文本框内容跟提示内容一样,提示内容会自然消失. ...

  9. elk 索引

    zjtest7-redis:/usr/local/logstash-2.3.4/config# cat logstash_agent.conf input { file { type => &q ...

  10. 高级爬虫工程师(Spider)-美团网-拉勾网-最专业的互联网招聘平台

    高级爬虫工程师(Spider)-美团网-拉勾网-最专业的互联网招聘平台 高级爬虫工程师(Spider)