linux编程之getopt

getopt -- 解析命令的可选项

【说明】getopt只是一个简单的解析命令可选项的函数,只能进行简单的格式命令解析,格式如下:

1、形如:cmd [-a][-b] //对短选项的解析;

2、形如:cmd [-a a_argument][-b b_argument] //对短选项及短选项的参数解析;

3、形如:cmd [-a[a_argument]] //选项a的参数也是可选的情况解析

原型:

#include <unistd.h>

extern char *optarg;
extern int optind, opterr, optopt;
int getopt(int argc, char * const argv[], const char *optstring);

描述:

1、getopt函数解析命令行参数,argcargv是调用main函数时传入的参数。传入的‘-‘开始的字符被解析为选项,getopt一次执行解析出一个option,如果循环执行,可以将argv中的全部option解析出来;

2、在getopt的执行中,每次进入都会更新optind变量,该变量指向下一个argv参数;

3、如getopt返回-1,表示argv[]中的所有选项被解析出,optind指向第一个非选项的argument元素;这里要注意,在getopt执行过程中会将单独的argument交换到argv数组的后面,option选项提前,如:cmd -a file1 -b file2,如果a/b均为不带参数的选项,这最终argv数组变为:cmd -a -b file1 file2;

4、optstring指定选项合法的选项,一个字符代表一个选项,在字符后面加一个‘:‘表示该选项带一个参数,字符后带两个‘:‘表示该选项带可选参数(参数可有可无),若有参数,optarg指向该该参数,否则optarg为0;

5、前面说了getopt会进行argv顺序的调整,但也可以通过设置optstring改变它的方式,这里有两种:

1) 如果optstring的第一个参数是‘+‘或者POSIXLY_CORRECT被设置,则getopt在原argv的顺序上遇到第一个非选项就返回-1;

2) 如果optstring的第一个参数是‘-‘,则会将所有的非选项当选项处理,并且返回1,用字符代码1表示该选项;

6、如果getopt不能识别一个选项字符,它会打印一个错误消息到stderr上,并将该字符存放到optopt中,返回‘?‘;调用程序可以设置opterr=0设置不打印错误信息;注意:要使能打印错误信息,optstring的第一个字符(或者在第一个字符是+/-之后)不能是‘:‘,否则也不会打印错误;

7、如果optstring中指定了option需要参数,但在命令行没有参数,那么getopt将返回‘?‘,如果在optstring的第一个字符(或者在第一个字符是+/-之后)是‘:‘,那么将返回‘:‘;

 

返回值:

1、返回类型为int,这个在编程的时候要注意,因为返回值类型范围要包含-1,很容易返回值接收定义为char,但在一些系统中char是无符号的,将导致程序错误;

2、当传入的argv中的选项全部被解析,getopt()返回-1,这也是getopt进行选项解析的循环截至条件;

3、如果argv中解析出optstring中描述的选项字符,则返回该字符,如果该选项指定了参数,则全局变量optarg指向该参数;

4、如果getopt遇到一个非optstring指定的选项字符,这表示该选项是未识别的,返回‘?‘,并且将该选项存放到全局变量optopt中;

5、如果optstring指定了选项必须带参数,但传入的相应option丢失了参数,返回值依赖于optstring的第一个字符,若第一个字符是‘:‘,返回‘:‘,否则返回‘?‘;由于非法的选项返回也是‘?‘,所以常常optstring的第一个字符指定为‘:‘;同时将该选项存放到全局变量 optopt中;

测试例程:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <string.h>
 5 #include <sys/types.h>
 6
 7 int main(int argc, char *argv[])
 8 {
 9         extern char *optarg;
10         extern int optind, opterr, optopt;
11         int i;
12         int ret;
13
14         for (i=0; i<argc; i++)
15         {
16                 printf ("argv[%d] %s\n", i, argv[i]);
17         }
18         printf ("\n");
19
20         while ((ret = getopt(argc, argv, ":a:b::c")) != -1)
21         {
22                 switch (ret) {
23                 case ‘a‘:
24                         printf ("option: %c argv: %s\n", ret, optarg);
25                         break;
26                 case ‘b‘:
27                         if (optarg)
28                                 printf ("option: %c argv: %s\n", ret, optarg);
29                         else
30                                 printf ("option: %c no argument\n", ret);
31                         break;
32                 case ‘?‘:
33                         printf ("encountered a unrecognized option: %c, argv: %s\n", optopt, argv[optind - 1]);
34                         break;
35                 case ‘:‘:
36                         printf ("option: %c missing argument\n", optopt);
37                         break;
38                 default:
39                         printf ("option: %c\n", ret);
40                         break;
41                 }
42         }
43
44         printf ("\noptind: %d\n\n", optind);
45         for (i=optind; i>0 && i<argc; i++)
46                 printf ("argv[%d] %s\n", i, argv[i]);
47
48         printf ("\n");
49         for (i=0; i<argc; i++)
50                 printf ("argv[%d] %s\n", i, argv[i]);
51
52         return 0;
53 }

然后我们运行测试例程,自己根据前面的描述进行一些分析:

[email protected]:./parse_cmdline -axxx -byyy

argv[0] ./parse_cmdline

argv[1] -axxx

argv[2] -byyy

option: a argv: xxx

option: b argv: yyy

optind: 3

argv[0] ./parse_cmdline

argv[1] -axxx

argv[2] -byyy

[email protected]:./parse_cmdline -a xxx -b yyy

argv[0] ./parse_cmdline

argv[1] -a

argv[2] xxx

argv[3] -b

argv[4] yyy

option: a argv: xxx

option: b no argument

optind: 4

argv[4] yyy

argv[0] ./parse_cmdline

argv[1] -a

argv[2] xxx

argv[3] -b

argv[4] yyy

从这个可以看出,带参数的option参数可以紧跟,也可以中间有空格;

[email protected]:./parse_cmdline -axxx -b yyy -c

argv[0] ./parse_cmdline

argv[1] -axxx

argv[2] -b

argv[3] yyy

argv[4] -c

option: a argv: xxx

option: b no argument

option: c

optind: 4

argv[4] yyy

argv[0] ./parse_cmdline

argv[1] -axxx

argv[2] -b

argv[3] -c

argv[4] yyy

[email protected]:./parse_cmdline -axxx -byyy -c

argv[0] ./parse_cmdline

argv[1] -axxx

argv[2] -byyy

argv[3] -c

option: a argv: xxx

option: b argv: yyy

option: c

optind: 4

argv[0] ./parse_cmdline

argv[1] -axxx

argv[2] -byyy

argv[3] -c

从这里可以看出,对于-b是可跟参数也可不跟参数的,参数必须紧跟,中间不能有空格。同时还可以看出:在有argument在argv中,最后出现了argv[]元素位置变化,选项前移了,而参数后移

[email protected]:./parse_cmdline -x

argv[0] ./parse_cmdline

argv[1] -x

encountered a unrecognized option: x, argv: -x

optind: 2

argv[0] ./parse_cmdline

argv[1] -x

[email protected]:./parse_cmdline -a

argv[0] ./parse_cmdline

argv[1] -a

option: a missing argument

optind: 2

argv[0] ./parse_cmdline

argv[1] -a

这里可以看出未识别的option,和丢失参数的option情况;

// 修改代码while ((ret = getopt(argc, argv, "a:b::c")) != -1)

[email protected]:./parse_cmdline -x

argv[0] ./parse_cmdline

argv[1] -x

./parse_cmdline: invalid option -- x

encountered a unrecognized option: x, argv: -x

optind: 2

argv[0] ./parse_cmdline

argv[1] -x

// 修改代码while ((ret = getopt(argc, argv, "+a:b::c")) != -1)

[email protected]:./parse_cmdline -x xxxx -ayyyy -bzzz kkkk

argv[0] ./parse_cmdline

argv[1] -x

argv[2] xxxx

argv[3] -ayyyy

argv[4] -bzzz

argv[5] kkkk

./parse_cmdline: invalid option -- x

encountered a unrecognized option: x, argv: -x

option: a argv: yyyy

option: b argv: zzz

optind: 4

argv[4] xxxx

argv[5] kkkk

argv[0] ./parse_cmdline

argv[1] -x

argv[2] -ayyyy

argv[3] -bzzz

argv[4] xxxx

argv[5] kkkk

这块代码说明了optstring第一个字符的作用,剩余的其他功能读者自己分析;

时间: 2024-12-14 12:05:05

linux编程之getopt的相关文章

Linux编程之ICMP洪水攻击

我的上一篇文章<Linux编程之PING的实现>里使用ICMP协议实现了PING的程序,ICMP除了实现这么一个PING程序,还有哪些不为人知或者好玩的用途?这里我将介绍ICMP另一个很有名的黑科技:ICMP洪水攻击. ICMP洪水攻击属于大名鼎鼎的DOS(Denial of Service)攻击的一种,一种是黑客们喜欢的攻击手段,这里本着加深自己对ICMP的理解的目的,也试着基于ICMP写一段ICMP的洪水攻击小程序. 洪水攻击(FLOOD ATTACK)指的是利用计算机网络技术向目的主机发

Linux编程之UDP SOCKET全攻略

这篇文章将对linux下udp socket编程重要知识点进行总结,无论是开发人员应知应会的,还是说udp socket的一些偏僻知识点,本文都会讲到.尽可能做到,读了一篇文章之后,大家对udp socket有一个比较全面的认识.本文分为两个专题,第一个是常用的upd socket框架,第二个是一些udp socket并不常用但又相当重要的知识点. 一.基本的udp socket编程 1. UDP编程框架要使用UDP协议进行程序开发,我们必须首先得理解什么是什么是UDP?这里简单概括一下. UD

【转】 linux编程之GDB调试

GDB是一套字符界面的程序集,可以用它在linux上调试C和C++程序,它提供了以下的功能: 1 在程序中设置断点,当程序运行到断点处暂停 2 显示变量的值,可以打印或者监视某个变量,将某个变量的值显示出来 3 单步执行 4 运行时修改变量的值 5 跟踪路径 6 线程切换 等等 下面以以下程序为例 当我们要使用GDB进行程序的调试时,在用GCC编译时需要加上-g,如下: GDB之所以能够进行程序的调试也是在于进行编译时的-g选项,当设置了这个选项的时候,GCC会向程序中塞入一下信息,作为GDB调

我的linux编程之路01

我的linux编程之路从现在开始!

Linux编程之PING的实现

void icmp_pack(struct icmp* icmphdr, int seq, int length) { int i = 0; icmphdr->icmp_type = ICMP_ECHO; //类型填回送请求 icmphdr->icmp_code = 0; icmphdr->icmp_cksum = 0; //注意,这里先填写0,很重要! icmphdr->icmp_seq = seq; //这里的序列号我们填1,2,3,4.... icmphdr->icmp

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

1.getopt 1.1 函数定义 int getopt(int argc, char * const argv[], const char *optstring);#include <unistd.h> 该函数用来解析命令行参数.前两个参数设为main函数的两个参数.optstring设为由该命令要处理的各个选项组成的字符串.选项后面带有冒号':'时,该选项是一个带参数的选项. 例如:make -f filename -n-f是一个带参数的选项,-n是一个没有参数的选项. 可以下面这样调用函

linux编程之awk

gawk是由GNU组织改良后的awk,这种语言在linux操作系统上,有着很好的应用,它不需要编译,比其它语言更为简洁,而且效率极高,还能与shell进行交互,是运维人员必不可少的编辑三剑客之一 gawk是一种报告生成器,它将文本读入内存,然后,结符合的显示在屏幕上 gawk的基本语法: gawk [options] 'program' file file - gawk [options] 'PATTERN{action}'file file- 1.gawk的输出,使用print和printf

Linux编程之Makefile(一)

我刚开始学Linux的时候,并没有用Makefile.写一个test.c ,然后直接gcc -o -g test test.c.后来文件一多,各种.c .h 文件.原来的方法是没法编译的.所以这时候就要靠Makefile. 先写一个简单的例子吧.现在有一段代码 #include<stdio.h> int main(int args,char *argv[]) { printf("hello,world!!"); return 0; } 稍微插一段编译原理:首先你的.c到Li

Linux编程之recvmsg和sendmsg函数

recvmsg 和 sendmsg 函数 #include <sys/types.h> #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_