深入理解getopt[通俗易懂]

深入理解getopt[通俗易懂]getopt–解析命令的可选项【说明】getopt只是一个简单的解析命令可选项的函数,只能进行简单的格式命令解析,格式如下:1、形如:cmd[-a][-b]//对短选项的解析;2、形如:cmd[-aa_argument][-bb_argument]//对短选项及短选项的参数解析;3、形如:cmd[-a[a_argument]]//选项a的参数也是可选的情况解析4…

大家好,又见面了,我是你们的朋友全栈君。

getopt – 解析命令的可选项

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

1、形如:cmd [-a][-b] //对短选项的解析;
2、形如:cmd [-a a_argument][-b b_argument] //对短选项及短选项的参数解析;
3、形如:cmd [-a[a_argument]] //选项a的参数也是可选的情况解析
4、形如:cmd [-ab]// cmd [-a][-b] 这样的形式也能解析

原型:

#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 的执行中,每次进入都会更新 option 变量,该变量指向下一个 argv 参数;
3、如 getopt 返回-1,表示 argv[] 中的所有选项被解析出,option 指向第一个非选项的 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 的第一个字符(或者在第一个字符是 +/- 之后)是 ‘:’,那么将返回 ‘:’;
8、如果在选项中有 “–”,并且前后是空格,其含义是强制终止 getopt 的继续执行,返回 -1,这个可以用来做一些特殊的处理;

返回值:

1、返回类型为 int,这个在编程的时候要注意,因为返回值类型范围要包含 -1,很容易返回值接收定义为 char,但在一些系统中 char 是无符号的,将导致程序错误;
2、当传入的 argv 中的选项全部被解析,getopt() 返回 -1,这也是 getopt 进行选项解析的循环截至条件;
3、如果 argv 中解析出 optstring 中描述的选项字符,则返回该字符,如果该选项指定了参数,则全局变量 optarg 指向该参数;
4、如果 getopt 遇到一个非 optstring 指定的选项字符,这表示该选项是未识别的,返回 ‘?’,并且将该选项存放到全局变量optopt 中;
5、如果 optstring 指定了选项必须带参数,但传入的相应 option 丢失了参数,返回值依赖于 optstring 的第一个字符,若第一个字符是 ‘:’,返回 ‘:’,否则返回 ‘?’;由于非法的选项返回也是 ‘?’,所以常常 optstring 的第一个字符指定为 ‘:’;同时将该选项存放到全局变量 optopt 中;

测试例程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{ 
      
        extern char *optarg;
        extern int optind, opterr, optopt;
        int i;
        int ret;

        for (i=0; i<argc; i++)
        { 
      
                printf ("argv[%d] %s\n", i, argv[i]);
        }   
        printf ("\n");

        while ((ret = getopt(argc, argv, ":a:b::c")) != -1)
        { 
      
                switch (ret) { 
   
                case 'a':
                        printf ("option: %c argv: %s\n", ret, optarg);
                        break;
                case 'b':
                        if (optarg)
                                printf ("option: %c argv: %s\n", ret, optarg);
                        else
                                printf ("option: %c no argument\n", ret);
                        break;
                case '?':
                        printf ("encountered a unrecognized option: %c, argv: %s\n", optopt, argv[optind - 1]);
                        break;
                case ':':
                        printf ("option: %c missing argument\n", optopt);
                        break;
                default:
                        printf ("option: %c\n", ret);
                        break;
                }   
        }

        printf ("\noptind: %d\n\n", optind);
        for (i=optind; i>0 && i<argc; i++)
                printf ("argv[%d] %s\n", i, argv[i]);

        printf ("\n");
        for (i=0; i<argc; i++)
                printf ("argv[%d] %s\n", i, argv[i]);

        return 0;
}

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

root@ParseCmdLine:./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

root@ParseCmdLine:./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参数可以紧跟,也可以中间有空格;

root@ParseCmdLine:./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

root@ParseCmdLine:./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[] 元素位置变化,选项前移了,而参数后移;

root@ParseCmdLine:./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

root@ParseCmdLine:./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)

root@ParseCmdLine:./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)

root@ParseCmdLine:./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 第一个字符的作用,剩余的其他功能读者自己分析;

root@ParseCmdLine:./parse_cmdline -axxx -- -byyyy
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] --
argv[3] -byyyy

option: a argv: xxx

optind: 3

argv[3] -byyyy

argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] --
argv[3] -byyyy

这一块说明了 “–” 的应用;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/133444.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 异步编程中的BeginInvoke和EndInvoke

    异步编程中的BeginInvoke和EndInvoke如果委托对象的调用列表中只有一个方法 引用方法 就可以异步执行这个方法 通过调用委托类特有的两个方法 BeginInvoke 和 EndInvoke 去执行 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp BeginInvoke 和 EndInvoke nbsp 的三种模式 nbsp BeginInvoke 方法的参数列表 nbsp 1 引用方法所需要的参数 nbsp nbsp 2 两个额外的参数 callback 参数和 state 参数 nbsp

    2025年11月12日
    2
  • 联想g510键盘如何拆装视频_联想g5080键盘怎么拆

    联想g510键盘如何拆装视频_联想g5080键盘怎么拆导致笔记本键盘失灵的原因有很多种,有时候是因为电脑系统的原因,但是大部分还是因为键盘本身的问题,如果是键盘本身的问题导致的笔记本键盘失灵,那么最多的解决方法就是拆卸该笔记本的键盘,然后分析问题的所在。下面小编就为大家介绍一下的方法吧,欢迎大家参考和学习。首先观察一下键盘正面,键盘靠一个弧形的卡口卡在掌托上的。如图:键盘左手面在桌上找一块大空地,周围不要放水或者…当键盘坏了,这时就需要更换了,笔…

    2025年12月9日
    3
  • 如何绘制qq图_python画图

    如何绘制qq图_python画图Q-Q图主要可以用来回答这些问题:两组数据是否来自同一分布PS:当然也可以用KS检验,利用python中scipy.stats.ks_2samp函数可以获得差值KSstatistic和P值从而实现判断。两组数据的尺度范围是否一致两组数据是否有类似的分布形状前面两个问题可以用样本数据集在Q-Q图上的点与参考线的距离判断;而后者则是用点的拟合线的斜率判断。用Q-Q图来分析分布的好处都有啥?(谁说对了…

    2022年8月10日
    12
  • Web安全之业务逻辑漏洞

    Web安全之业务逻辑漏洞业务逻辑不同的项目有不同的功能,不同的功能需要不同的代码实现,实现这些核心功能的代码就叫业务逻辑。业务逻辑漏洞业务逻辑漏洞是指由于程序逻辑不严谨或逻辑太复杂,导致一些逻辑分支不能正常处理或处理错误。常见的业务逻辑漏洞业务逻辑漏洞挖掘过程确定业务流程—>寻找流程中可以被操控的环节—>分析可被操控环节中可能产生的逻辑问题—>尝试修改参数触发逻辑问题业务逻辑漏洞1.URL跳转漏洞1.1.URL跳转概述1.2.触发方式及绕或技巧1.3.修复方法2.短信邮箱轰炸漏洞2.1.短信邮.

    2022年6月1日
    35
  • IOS基金会_ UICollectionView简单易用

    IOS基金会_ UICollectionView简单易用

    2022年1月12日
    39
  • java 雪崩效应,七、微服务架构中的“雪崩效应”

    java 雪崩效应,七、微服务架构中的“雪崩效应”1.雪崩效应在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务堆积,最终导致服务瘫痪。其实,在单体服务中,高并发也会导致服务瘫痪。见下一章,Jmeter模拟微服务当中的高并发场景在分布式系统中,由于网络原因或自身的原因,服…

    2022年7月13日
    15

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号