getopt()、getopt_long函数详细解释!保证看明白

这篇具有很好参考价值的文章主要介绍了getopt()、getopt_long函数详细解释!保证看明白。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

研究select模型的时候看到CSDN很多博主用到了getopt函数,这个模型弄的一脸懵,getopt先弄明白。。

getopt() 方法是用来分析命令行参数的,它的作用是判断你输入的命令行是否正确。

1.命令行组成

我们举例说明命令行组成

ls -l  -a   /etc

这行命令的意思是:详细列出/etc这个文件夹下所有文件,包括隐藏文件的信息

ls   命令 (command)

a  和l 都是   选项 (option) ,选项前面,必须有短横线这才叫选项 

/etc 这叫 operand ,操作对象

grep -i water aaa.log

 这行命令的意思是:在aaa.log文件中,查找water字符串,不区分大小写

grep  命令

i  选项

water ,正则表达式中叫匹配模式pattern ,命令行中叫做 选项参数 ( option argument)

aaa.log  操作对象 

比方说我瞎写 了一个aaa.log 其中内容是

water
water222
333water
444aaabbcc
555line
footabl
footballwater lunch
aaawatersuper

那么上书命令的 执行结果是

water
water222
333water
footballwater lunch
aaawatersuper
 

然后很多命令有不止一个参数,继续拿grep举例

grep -f aaa.log water aaa.log

 这个命令意思是:在结果中每一行都打印一遍aaa.log 这个文件名,在文件aaa.log中查找water字符串,不区分大小写。然后执行结果是

aaa.log:water
aaa.log:water222
aaa.log:333water
aaa.log:444aaabbcc
aaa.log:555line
aaa.log:footabl
aaa.log:footballwater lunch
aaa.log:aaawatersuper

我晕死,我也不知道-f怎么不匹配的现在也在结果中变红了匹配了,但是这先不重要,弄明白命令行的组成就行了

2. getopt函数

2.1 函数原型

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

2.2  参数argc  argv是什么意思

 argc是你在命令行中的所有参数个数,argv[]是所有参数组成的数组,外加可执行文件名

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char* argv[]){
    printf("参数个数是%d\n",argc);
    for(int i=0;i<argc;i++){
        printf("参数argv[%d] 是%s\n",i,argv[i]);
    }

return 0;
}

把这个代码gcc 编译成a.out 

然后你 ./a.out   hello world cat dog 回车,结果显示

参数个数是5

argv[0] 是 ./a.out

argv[1] 是 hello

argv[2] 是 world

argv[3] 是 cat

argv[4] 是 dog

2.3这个函数有几个全局变量

读者可能会奇怪,这个函数还有第三个参数optstring呢!它是一个常量字符串,你怎么函数参数没说完又介绍别的了! 我先介绍完这个函数的几个全局变量,下一节再介绍这个函数的第三个参数,因为optstring的写法影响了他们的值

getopt()函数有几个系统默认的全局变量,可以直接拿出来使用

  • optarg:当前选项的参数字符串 ,要么是null ,要么是你写的,或者系统捕获的,它认为的选项参数。
  • optind:下一个查找的位置,在所有命令行中的索引。初始值:1 

           这个optind后面有例子进行解释

  • optopt:当发现无效选项字符时,optopt 就等于这个无效选项字符
  • opterr:1或者0 ,一般大家不用管,都是1。

opterr ==0时,不打印错误信息。

opterr==1时,如果你输入的命令行有错误,getopt()会打印错误信息到屏幕。

2.4 optstring的写法

函数的第三个参数optstring是一个常量字符串,

//学习get_opt()
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char* argv[]){
    printf("参数个数是%d\n",argc);
    for(int i=0;i<argc;i++){
        printf("参数argv[%d] 是%s\n",i,argv[i]);
    }
    printf("test getopt func\n");
    int ret;
    while ((ret=getopt(argc, argv,"abc:")) !=-1){
	printf("返回值ret =%d ,int optind= %d,它的选项参数optarg =%s, 错误选项optopt =%c\n",ret,optind,optarg,optopt);
    }
return 0;
}

 上述代码表示,只有-a  -b -c 是合法选项,  -c 后面必须接参数,  abc 可以不全,但是 c后面必须有参数 。

2.5 函数返回值

getopt()函数在挨个搜索命令行时, 它返回它找到的参数,但是把这个字符char转换成int,所以结果是整数。

当它发现错误的时候,返回值是 “ ?” 。(但是如果optstring开头就是一个冒号,那么这个还会变化,后面再说)

当全部命令行扫描完毕,它返回-1。接下来,我们实验下我各种不同的命令行写法, 或者我故意写错会报什么

2.5.1 完全正确的输入

我输入    ./test2 -a -b -c wang
参数个数是5
参数argv[0] 是./test2
参数argv[1] 是-a
参数argv[2] 是-b
参数argv[3] 是-c
参数argv[4] 是wang
test getopt func
返回值ret =97 ,int optind= 2,它的选项参数optarg =(null), 错误选项optopt =
返回值ret =98 ,int optind= 3,它的选项参数optarg =(null), 错误选项optopt =
返回值ret =99 ,int optind= 5,它的选项参数optarg =wang, 错误选项optopt =

都对,所以到最后也没抓到哪个参数错误 (optopt一直是空的)

看一下返回值ret ,97 就是ASC II代码中的a  , 98对应b 。。。

注意~ int optind 为什么一下子从3跳到5了??因为optind默认初始值是1 ,也就是从你输入的-a 开始扫描  (编号为0的是./test2   命令名称本身。),扫描完-a 返回了一个值,optind 就等于2了,表示下一次从编号为2的 -b 开始扫描,然后扫描完-b optind =3 表示下次从 -c开始扫描,因为-c 必须跟个选项参数,这个选项参数wang 的编号是4 ,所以扫描完 -c ,getopt()函数返回 -1了,optind =5 表明接下来要从编号为5的地方开始扫描 (当然这里没有后面的编号为5的东西了)

 2.5.2  有一个不该出现的选项

./test2 -a -b -d wang
参数个数是5
参数argv[0] 是./test2
参数argv[1] 是-a
参数argv[2] 是-b
参数argv[3] 是-d
参数argv[4] 是wang
test getopt func
返回值ret =97 ,int optind= 2,它的选项参数optarg =(null), 错误选项optopt =
返回值ret =98 ,int optind= 3,它的选项参数optarg =(null), 错误选项optopt =
./test2: invalid option -- 'd'
返回值ret =63 ,int optind= 4,它的选项参数optarg =(null), 错误选项optopt =d

注意,63查一下ASCII 码,就是 “ ?”

2.5.3 有一个选项忘记带选项参数

 ./test2   -a   -b   -c
参数个数是4
参数argv[0] 是./test2
参数argv[1] 是-a
参数argv[2] 是-b
参数argv[3] 是-c
test getopt func
返回值ret =97 ,int optind= 2,它的选项参数optarg =(null), 错误选项optopt =
返回值ret =98 ,int optind= 3,它的选项参数optarg =(null), 错误选项optopt =
./test2: option requires an argument -- 'c'
返回值ret =63 ,int optind= 4,它的选项参数optarg =(null), 错误选项optopt =c

可以看到,返回值仍然是 63 对应ASC II 码中“ ? ”

2.5.4 打乱顺序

./test2 -b -c -d wang
参数个数是5
参数argv[0] 是./test2
参数argv[1] 是-b
参数argv[2] 是-c
参数argv[3] 是-d
参数argv[4] 是wang
test getopt func
返回值ret =98 ,int optind= 2,它的选项参数optarg =(null), 错误选项optopt =
返回值ret =99 ,int optind= 4,它的选项参数optarg =-d, 错误选项optopt =

没抓到错误,因为 选项c 后面的-d被认为是选项参数了,后面的wang酒忽略不看了。

这里也注意optind 从2跳到了4 ,因为扫描完-c  后面的 “ -d  " 被当做 c 的选项参数直接跳了过去,下次扫描从编号为4的 wang开始,但是此时getopt()函数已经运完了 ,返回了。因为它认为后面的wang没有意义了。

2.5.4. 有两个冒号

一个冒号表示选项后必须有参数,没有参数就会报错。如果有两个冒号的话,那么这个参数就是可选参数了,即可有可没有。

   例: const char *optstring = "abc::";  有三个选项-a -b  -c,其中c选项后有两个冒号,表示后面可选参数,但是!!此时c后面如果有选项参数,必须紧紧跟在c后面 。这种情况我还没见过linux哪个命令有这样的情况。 但是选项参数必须跟在选项后面的例子,可以看tar命令 的-f选项:

 tar  -zcv  -f  yasuo.tar.gz  fileA  fileB   fileC

把fileA  B C 三个文件打包,并用gzip的支持进行压缩,新建立的压缩包名为yasuo.tar.gz, 4个选项zcvf分别表示

-z  用gzip的方式

-c 新建打包文件

-v  把这个过程中处理哪些文件列出在屏幕上

-f  后面紧跟待处理文件,如果是-c(新建)那就跟“新建压缩文件名” 如果是-x (解压缩),f后面跟“待解压缩文件名”

这个-f  后面必须紧跟着文件名字  上述代码你可以写成 tar -zcvf  yasuo.tar.gz  fileA  fileB  fileC  但是你写成tar  -zfcv  或者 -cvfz   XXXX 就错了。

2.5.5 optstring开头的冒号

我们设置optstring的首字符为冒号":",在这种情况下,如果你输入了错误的命令行,屏幕上啥也没有。这时候怎么知道你输入的是否有误?原来是getopt()函数返回值变了。

当发生无法识别的选项错误时,例:optstringt = “abc”  你输入选项 -a -b -q 。getopt()返回字符"?",

当发生丢失选项参数错误时返回字符":"。例:optstringt = “abc : ”你输入选项 -c但是后面没接选项参数。

这样我们就可以很轻松地分辨出错误类型了。

3. getopt_long() 函数

3.1 长参数举例

getopt_long()函数其实可以参数写的跟getopt()函数一模一样,但是它还可以接受长参数。长参数在linux中最常见的应该是 --help了,几乎任何命令都可以加一个  --help来查看帮助 ,例如 ls --help

又例如,我自己创建了一个文件夹叫做dirA (linux中,文件夹都叫 “目录” ) ,然后这个目录中我瞎写了三个文件aaa.log ,   bbb.log   ,ccc.log  然后我想把dirA打包压缩,新建为bag3.tar.gz 但是aaa.log不想打包,

tar   -zcvf    bag3.tar.gz    --exclude=aaa.log    dirA

 由于有参数v 所以能把处理过程展示在屏幕,发现是

dirA/
dirA/bbb.log
dirA/ccc.log

真的避开了aaa.log  

此处的 --exclude=PATTREN 也是长参数。 

3.2  函数原型


#include <getopt.h>
int getopt_long(int argc,  char * const argv[],     const char *optstring,   

            const struct option *longopts,

           int *longindex);

比getopt 函数多了两个参数  const struct option *longopts,   int *longindex。

前者是一个数组,其中每个元素都是struct option。 先看一下这个option结构体的组成

struct option {
    const char *name;
    int has_arg;
    int *flag;
    int val;
};
  • name指明长选项的名称;
  • has_arg指明该选项是否带参数。0没有参数,1需要参数,2有没有都行;

            第一种写法举例  ls --help   //查看ls命令帮助

            需要参数的选项写法举例 参照前面tar打包命令的例子  --exclude=aaa.log   --exclude aaa.log都行,都表示处理时忽略aaa.log文件。

            第三种的写法:只能写成 --exclude=aaa.log

  • flag指明长选项如何返回,

              flag ==NULL时,getopt_long()函数返回val的值。最好是 NULL 

              flag !=NULL时,getopt_long()函数返回0。 flag指向的值赋值为val变量的值。

              如果该长选项没有发现,flag指向的值保持不变;

  • val是一个字符常量 ,(例如 'a ' , 'q'  )。val要么等于getopt_long ()函数返回的值,要么等于flag指针所指的变量的值。

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

3.3 一个简单例子 

man getopt_long 回车,就可以看到这个例子,我又删减了一些代码

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>

int main(int argc, char **argv){
    int c;
    while (1) {    
        int option_index = 0;
        static struct option long_options[] = {
            {"add",     1, NULL,  0 },
            {"append",  0,NULL,  0 },
	        {"delete",  1, NULL,  0 },
            {"verbose", 0,NULL,  0 },
	        {"create",  1, NULL, 'c'},
            {"file",    1,NULL,  0 },
            {0,0, 0,0 }
        };
        c  = getopt_long(argc, argv, "abc:",long_options, &option_index);
        if (c == -1)
               break;
        switch (c) {
	        case 'a':
                printf("option a\n");
                break;
            case 'b':
                printf("option b\n");
                break;
            case 'c':
                printf("option c with optarg =  '%s'\n", optarg);
                break;
            case '?':
                printf("返回值是?\n");
		        break;
            default:
                 printf("?? getopt returned character code 0%o ??\n", c);
                break;
	    }
    }
    if (optind < argc) {
        printf("non-option ARGV-elements: ");
        while (optind < argc){
            printf("argv[optind++] is %s\n ", argv[optind++]);
        }
        printf("\n");
    }

exit(EXIT_SUCCESS);
}

 这篇代码意思是,命令行里可以有abc三个短选项,c后面必须接参数,长选项可以有add ,append, delete等,其中add, delete ,create , file 后面必须有参数。把代码编译成可执行文件longc

./longc -a -b -c wang 短选项的实验跟上面一样,接下来只试长选项的

./longc --add
./longc: option '--add' requires an argument
返回值是?

./longc --append
?? getopt returned character code 00 ??

./longc --create hello
option c with optarg =  'hello'

注意,--create 这个长选项,返回值val是c 也就是说,--create 可以缩写成-c 

在那个结构体中,最后一个val值,就是本行长参数可以采用的单字符缩写,如果是0 就表示没有缩写。

3.4两个函数的关系

getopt_long函数其实可以完整包涵getopt()函数的功能,特殊情况:

1)如果你只想接受短选项 -a  -b这种,你的第三个参数写NULL就行

3.4中的例子,假如你的代码修改为

 c  = getopt_long(argc, argv, "abc:",NULL,NULL);

./long2 --add     假如再执行这个错误命令的话,结果是
./long2: invalid option -- '-'
返回值是?
option a
./long2: invalid option -- 'd'
返回值是?
./long2: invalid option -- 'd'
返回值是?
 

2)如果你只想接受长选项,那第二个参数写"" 。

3.4中的例子,假如你的代码修改为

c  = getopt_long(argc, argv, "",long_options, &option_index);编译,执行

./long2 -a  (回车),结果是:
./long2: invalid option -- 'a'
返回值是?

4.参考文章

CSDN博主文章

另一个博主的文章

更多getopt -long的参考
 文章来源地址https://www.toymoban.com/news/detail-811100.html

到了这里,关于getopt()、getopt_long函数详细解释!保证看明白的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 就业班 第三阶段(负载均衡) 2401--4.19 day3

    二、企业 keepalived 高可用项目实战 1、Keepalived VRRP 介绍 2、Nginx+keepalived实现七层的负载均衡 Nginx通过Upstream模块实现负载均衡 upstream 支持的负载均衡算法 主机清单: 主机名 ip 系统 用途 Proxy-master 172.16.147.155 centos7.5 主负载 Proxy-slave 172.16.147.156 centos7.5 主备 Real-server1 172.16.147

    2024年04月29日
    浏览(36)
  • 一文弄明白KeyedProcessFunction函数

    KeyedProcessFunction是Flink用于处理KeyedStream的数据集合,它比ProcessFunction拥有更多特性,例如状态处理和定时器功能等。接下来就一起来了解下这个函数吧 了解一个函数怎么用最权威的地方就是 官方文档 以及注解,KeyedProcessFunction的注解如下 上面简单来说就是以下四点 Flink中输

    2024年02月22日
    浏览(44)
  • 就业班 第三阶段(ansible) 2401--4.15 day1 ansible1 模块+配置

    1、ansible 是什么? 2、ansible 特点 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作; 默认使用SSH协议对设备进行管理; 有大量常规运维操作模块,可实现日常绝大部分操作; 配置简单、功能强大、扩展性强; 支持API及自定义模块,可通过Python轻松扩展; 通

    2024年04月22日
    浏览(37)
  • c++类开发的第三篇(讲明白友元函数和this指针)

    c++实现了 封装 , 数据 和 处理数据的操作(函数) 是分开存储的。 c++中的 非静态数据成员 直接内含在类对象中,就像c语言的struct一样。 成员函数并不会出现在对象中,而是作为类的一部分存储在代码段中,需要通过对象或对象指针进行调用。成员函数可以访问类的所有成员

    2024年02月21日
    浏览(47)
  • Ubuntu20.04搭建PX4仿真环境及XTDrone开发平台(最详细最明白)

    PX4-Autopilot仿真平台是由PX4官方提供的集虚拟px4固件、真机烧录固件、gazebo环境及模型于一体的平台,用户可以自己编写程序,通过mavros接口与虚拟px4固件进行mavlink协议的通讯,并在gazebo中显示虚拟世界和模型。因此PX官方手册里给了一个经典的例程:offboard.cpp和offboard.py,让

    2024年02月04日
    浏览(146)
  • JDK的安装与环境配置(超级详细,保证成功)

    如果你是一个才学习Java语言的小白,第一步应该就是安装JDK并配置环境了。在这里出一个超级详细的教程,希望可以帮助到你 首先,先把下载JDK的地址挂上:https://www.oracle.com/java/technologies/downloads/archive/ JDK的最新版本: Standard Edition(标准版)的最新版:jdk 14。 Early-Access(

    2024年02月05日
    浏览(52)
  • 【Linux 】getopts 可选参数_Bash技巧:介绍 getopts 内置命令解析选项参数的用法

    在 Linux bash shell 中,内置了一个 getopts 命令,可以处理以 ‘-’ 开头的选项参数。本篇文章通过多个实例详解 getopts 命令的用法。 getopts 命令简介 在 bash shell 上执行命令,常常会用到一些选项参数来指定不同的操作。例如 ls 命令的 -l、-a 选项等。 我们在编写 shell 脚本时,也

    2024年02月07日
    浏览(39)
  • SiLu激活函数解释

    在yolo v5中,我们使用了SiLu激活函数 首先,了解一下激活函数的作用: 激活函数在神经网络中起到了非常重要的作用。以下是激活函数的一些主要功能: 引入非线性:激活函数的主要目标是在模型中引入非线性。这是因为,如果没有激活函数,无论神经网络有多少层,它都

    2024年02月07日
    浏览(39)
  • realloc函数用法解释

    realloc函数是将数组扩容的一个函数 用法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。 具体工作方法: 假设有一个p指针指向一个数组空间,如下图所示 想在想要使这个数组的空间变为原来的2倍,realloc函数就会在p指向的这个数组空间后面申请一段

    2024年02月12日
    浏览(54)
  • matlab中repmat()函数解释

    repmat意思是 复制和平铺矩阵,何为平铺?举个简单例子   如上述结果可知,其将矩阵(0  1)复制以及向右向下平铺成一个以矩阵(0  1)为单位的33阶的矩阵。 故总结一般repmat函数有如下两种形式:                                             A=[1,2,3,4]  repmat(A,3)

    2024年02月11日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包