如何分析命令行参数

简介:

如何分析命令行参数

    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,还有几点说明:

1、如果选项带参数,该选项后接冒号,比如上例中optstring为"a:b",指示a带参数,b没有参数;

2、如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;

3、如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回'?',和无法识别的参数返回一样);

4、如果optstring的开头字符为'+',表明一但遇到一个无选项参数,马上停止扫描,随后的部分当作参数来解释;

5、如果optstring的开头字符为'-',表明如果遇到无选项参数,则把它当作选项1(不是字符'1')的参数。

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

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

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

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

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

11、每当解析完一个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 ’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。


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"


目录
相关文章
|
自然语言处理 物联网 异构计算
比LoRA还快50%的微调方法来了!一张3090性能超越全参调优,UIUC联合LMFlow团队提出LISA
【4月更文挑战第3天】伊利诺伊大学香槟分校和LMFlow团队推出LISA,一种新型微调技术,用于解决大型语言模型的内存消耗问题。LISA基于层重要性采样,随机冻结中间层,降低内存使用,同时提供比LoRA更快的训练速度和更高性能。实验显示,LISA在相似或更低的GPU内存消耗下,超越LoRA和全参数调优。该方法提高了资源受限环境下的微调效率,有望成为LoRA的有效替代,但仍然面临内存限制和随机性影响的问题。
358 4
比LoRA还快50%的微调方法来了!一张3090性能超越全参调优,UIUC联合LMFlow团队提出LISA
|
10月前
|
存储 关系型数据库 数据库
极简开发,极速上线:构建端到端大模型应用
本文将以一个经典的 RAG(检索增强生成)知识问答系统为例,详细介绍从智能体设计到最终应用部署的全流程。
1454 82
|
10月前
|
机器学习/深度学习 人工智能 C++
《CMake:掌控 C++人工智能项目编译的魔法棒》
在 C++ 人工智能项目的开发中,CMake 作为一款强大的构建工具,能够高效管理项目的编译流程。本文深入探讨了如何利用 CMake 处理复杂的项目结构、管理库文件链接、定制编译选项、支持跨平台编译以及生成和管理构建系统,帮助开发者高效构建、扩展和维护 C++ 人工智能项目。
163 17
|
12月前
|
消息中间件 存储 NoSQL
物联网设备频繁断网,如何打赢智慧社区的流量洪峰之战?
本文详细介绍了智慧社区中物联网(IOT)技术的应用,重点讨论了物联网流量洪峰的处理方法。文章分析了上行和下行消息的特点,并提出了上下行拆分、多泳道消息队列、实时消息优先处理、连接计算存储分离及推拉结合的消息策略,以优化消息队列,确保系统稳定运行。通过这些技术手段,智慧社区的物联网设备能在各种场景中保持高效运作。
183 2
|
NoSQL 关系型数据库 MySQL
Vgo-适合golang初学者的开源框架
# Vgo Vgo是一款基于Gin的开源服务端框架,集成了Redis、Mysql、JWT及队列等技术栈,适合Golang初学者。项目包括Vgo-Gitee和VgoAdmin-Gitee,可通过克隆仓库并按照安装指南进行部署。其目录结构清晰,涵盖路由、模型、后台接口等功能模块,更多功能持续开发中。
274 3
|
监控 算法 数据挖掘
ERP系统中的生产线排程与调度优化解析
【7月更文挑战第25天】 ERP系统中的生产线排程与调度优化解析
521 6
|
JavaScript Java 测试技术
基于SpringBoot+Vue的高校社团管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的高校社团管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
225 0
|
机器学习/深度学习 人工智能 算法
人工智能在医学领域的局限性
随着科技发展,人工智能技术在教育领域中的应用已取得较大进展。近年来,人工智能(AI)技术和由其引发的大数据时代自社会的各个层面包括我们的思维、生活方式和工作模式产生了巨大的变革;其与医学的结合给医疗系统带来深远的影响。从互联网到云计算,再到由大数据集合而成的人工智能,不断更新的处理手段使医疗行业也开始尝试新的转变,从传统的人工诊疗、教学模式逐步转变为依据机器学习来获取更高效的信息,并在医学多个领域已有比较广泛的应用。本文将从人工智能在医学领域的优势、当前的进展、应用、局限性和未来方向来进行综述。
741 1
|
安全 开发工具
微信小游戏制作工具中的键盘插件的使用
微信小游戏制作工具中的键盘插件的使用
889 0
|
存储 数据可视化 搜索推荐
一文读懂快速开发平台
一文读懂快速开发平台
337 0