人脸识别 angularjs vue中文网 vue开发文档 vue动态绑定class 管理后台ui 河南普通话考试报名 android富文本框架 java解析json数组 input取消边框 mysql插入 python中get函数 python中open python异常 python例子 python读文件 python打开文件夹 java正则表达式详解 java语言代码大全 java的random java中class java定义字符串 linux启动 java程序设计基础 pr转场特效下载 linux端口映射 微信砍价活动怎么做 语音分析软件 ug拔模 fireworks 全能音频转换通 1500左右性价比最高的手机 类似迅雷的下载软件 cdr透明度怎么调 论文封面怎么做 linux解压rar 方正兰亭粗黑简体 J9 cia转cci 力学分析软件
当前位置: 首页 > 学习教程  > 编程语言

浅析linux的命令行的参数getopt_long函数

2021/1/28 23:00:20 文章标签:

前言 在linux中,经常需要各种命令,通常情况下都会带各种参数,而这些参数是如何解析的呢?通常使用GNU C提供的函数getopt、getopt_long、getopt_long_only函数来解析命令行参数。 一、关于命令行参数 命令行参数可以分为两类&am…

前言

在linux中,经常需要各种命令,通常情况下都会带各种参数,而这些参数是如何解析的呢?通常使用GNU C提供的函数getopt、getopt_long、getopt_long_only函数来解析命令行参数。

一、关于命令行参数

命令行参数可以分为两类,一类是短选项,一类是长选项,短选项在参数前加一杠"-",长选项在参数前连续加两杠"–",如下表(ls 命令参数)所示,其中-a,-A,-b都表示短选项,–all,–almost-all, --author都表示长选项。他们两者后面都可选择性添加额外参数。比如–block-size=SIZE,SIZE便是额外的参数。

在这里插入图片描述

二、getopt_long函数

getopt函数只能处理短选项,而getopt_long函数两者都可以,可以说getopt_long已经包含了getopt_long的功能。因此,这里就只介绍getopt_long函数。而getopt_long与getopt_long_only的区别很小,等介绍完getopt_long,在提起会更好。

#include <unistd.h>  
extern char *optarg;  
extern int optind, opterr, optopt;  
#include <getopt.h>
int getopt(int argc, char * const argv[],const char *optstring);  
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);

参数以及返回值介绍(以上三个函数都适用):

1、argc和argv和main函数的两个参数一致。

2、optstring: 表示短选项字符串。

形式如“a:b::cd:“,分别表示程序支持的命令行短选项有-a、-b、-c、-d,冒号含义如下:
(1)只有一个字符,不带冒号——只表示选项, 如-c
(2)一个字符,后接一个冒号——表示选项后面带一个参数,如-a 100
(3)一个字符,后接两个冒号——表示选项后面带一个可选参数,即参数可有可无, 如果带参数,则选项与参数直接不能有空格
形式应该如-b200

3、longopts:表示长选项结构体。结构如下:

struct option 
{  
     const char *name;  
     int         has_arg;  
     int        *flag;  
     int         val;  
};  
eg:
 static struct option longOpts[] = {
      { "daemon", no_argument, NULL, 'D' },
      { "dir", required_argument, NULL, 'd' },
      { "out", required_argument, NULL, 'o' },
      { "log", required_argument, NULL, 'l' },
      { "split", required_argument, NULL, 's' },
      { "http-proxy", required_argument, &lopt, 1 },
      { "http-user", required_argument, &lopt, 2 },
      { "http-passwd", required_argument, &lopt, 3 },
      { "http-proxy-user", required_argument, &lopt, 4 },
      { "http-proxy-passwd", required_argument, &lopt, 5 },
      { "http-auth-scheme", required_argument, &lopt, 6 },
      { "version", no_argument, NULL, 'v' },
      { "help", no_argument, NULL, 'h' },
      { 0, 0, 0, 0 }
    };

(1)name:表示选项的名称,比如daemon,dir,out等。

(2)has_arg:表示选项后面是否携带参数。该参数有三个不同值,如下:

a: no_argument(或者是0)时 ——参数后面不跟参数值,eg: --version,–help b:
required_argument(或者是1)时 ——参数输入格式为:–参数 值 或者 --参数=值。eg:–dir=/home c:
optional_argument(或者是2)时 ——参数输入格式只能为:–参数=值

(3)flag:这个参数有两个意思,空或者非空。

a:如果参数为空NULL,那么当选中某个长选项的时候,getopt_long将返回val值。
eg,可执行程序 --help,getopt_long的返回值为h. b:如果参数不为空,那么当选中某个长选项的时候,getopt_long将返回0,并且将flag指针参数指向val值。
eg: 可执行程序 --http-proxy=127.0.0.1:80 那么getopt_long返回值为0,并且lopt值为1。

(4)val:表示指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值val。

4、longindex:longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值。

5、全局变量:

    (1)optarg:表示当前选项对应的参数值。

    (2)optind:表示的是下一个将被处理到的参数在argv中的下标值。

    (3)opterr:如果opterr = 0,在getopt、getopt_long、getopt_long_only遇到错误将不会输出错误信息到标准输出流。opterr在非0时,向屏幕输出错误。

    (4)optopt:表示没有被未标识的选项。

6、返回值:

  1. 如果短选项找到,那么将返回短选项对应的字符。
  2. 如果长选项找到,如果flag为NULL,返回val。如果flag不为空,返回0
  3. 如果遇到一个选项没有在短字符、长字符里面。或者在长字符里面存在二义性的,返回“?”
  4. 如果解析完所有字符没有找到(一般是输入命令参数格式错误,eg: 连斜杠都没有加的选项),返回“-1”
  5. 如果选项需要参数,忘了添加参数。返回值取决于optstring,如果其第一个字符是“:”,则返回“:”,否则返回“?”。

注意:

(1)longopts的最后一个元素必须是全0填充,否则会报段错误

(2)短选项中每个选项都是唯一的。而长选项如果简写,也需要保持唯一性。

三、测试(自行测试)

#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",     required_argument, 0,  0 },
            {"append",  no_argument,       0,  0 },
            {"delete",  required_argument, 0,  0 },
            {"verbose", no_argument,       0,  0 },
            {"create",  required_argument, 0, 'c'},
            {"file",    required_argument, 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(EXIT_SUCCESS);
}

2、自己项目相关一个例子。

#include<stdio.h>
#include <getopt.h>
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
 
void showUsage() {
  //cout << "Usage: " << PACKAGE_NAME << " [options] URL ..." << endl;
  cout << "Options:" << endl;
  cout << " -d, --dir=DIR              The directory to store downloaded file." << endl;
  cout << " -o, --out=FILE             The file name for downloaded file." << endl;
  cout << " -l, --log=LOG              The file path to store log. If '-' is specified," << endl;
  cout << "                            log is written to stdout." << endl;
  cout << " -D, --daemon               Run as daemon." << endl;
  cout << " -s, --split=N              Download a file using s connections. s must be" << endl;
  cout << "                            between 1 and 5. If this option is specified the" << endl;
  cout << "                            first URL is used, and the other URLs are ignored." << endl;
  cout << " --http-proxy=HOST:PORT     Use HTTP proxy server. This affects to all" << endl;
  cout << "                            URLs." << endl;
  cout << " --http-user=USER           Set HTTP user. This affects to all URLs." << endl;
  cout << " --http-passwd=PASSWD       Set HTTP password. This affects to all URLs." << endl;
  cout << " --http-proxy-user=USER     Set HTTP proxy user. This affects to all URLs" << endl;
  cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl;
  cout << " --http-auth-scheme=SCHEME  Set HTTP authentication scheme. Currently, BASIC" << endl;
  cout << "                            is the only supported scheme." << endl;
  cout << " -v, --version              Print the version number and exit." << endl;
  cout << " -h, --help                 Print this message and exit." << endl;
  cout << "URL:" << endl;
  cout << " You can specify multiple URLs. All URLs must point to the same file" << endl;
  cout << " or a download fails." << endl;
  cout << "Examples:" << endl;
  cout << " Download a file by 1 connection:" << endl;
  cout << "  aria2c http://AAA.BBB.CCC/file.zip" << endl;
  cout << " Download a file by 2 connections:" << endl;
  cout << "  aria2c -s 2 http://AAA.BBB.CCC/file.zip" << endl;
  cout << " Download a file by 2 connections, each connects to a different server." << endl;
  cout << "  aria2c http://AAA.BBB.CCC/file.zip http://DDD.EEE.FFF/GGG/file.zip" << endl;
  cout << "Reports bugs to <tujikawa at rednoah dot com>" << endl;
}
 
int main(int argc, char* argv[]) {
  bool stdoutLog = false;
  string logfile;
  string dir;
  string ufilename;
  int split = 0;
  bool daemonMode = false;
  int c;
 
 
  while(1) {
    int optIndex = 0;
    int lopt;
    static struct option longOpts[] = {
      { "daemon", no_argument, NULL, 'D' },
      { "dir", required_argument, NULL, 'd' },
      { "out", required_argument, NULL, 'o' },
      { "log", required_argument, NULL, 'l' },
      { "split", required_argument, NULL, 's' },
      { "http-proxy", required_argument, &lopt, 1 },
      { "http-user", required_argument, &lopt, 2 },
      { "http-passwd", required_argument, &lopt, 3 },
      { "http-proxy-user", required_argument, &lopt, 4 },
      { "http-proxy-passwd", required_argument, &lopt, 5 },
      { "http-auth-scheme", required_argument, &lopt, 6 },
      { "version", no_argument, NULL, 'v' },
      { "help", no_argument, NULL, 'h' },
      { 0, 0, 0, 0 }
    };
    c = getopt_long(argc, argv, "Dd:o:l:s:vh", longOpts, &optIndex);
    printf("返回值: %c\n",c);
    if(c == -1) {
      break;
    }
    switch(c) {
    case 0:{
      switch(lopt) {
      case 1: {
	printf("1: %s\n",optarg);
	break;
      }
      case 2:
	printf("2: %s\n",optarg);
	break;
      case 3:
	printf("3: %s\n",optarg);
	break;
      case 4:
	printf("4: %s\n",optarg);
	break;
      case 5: 
	printf("5: %s\n",optarg);
	break;
      case 6:
	printf("6: %s\n",optarg);
	break;
      }
      break;
    }
    case 'D':
      printf("D: %s\n",optarg);
      break;
    case 'd':
      printf("d: %s\n",optarg);
      break;
    case 'o':
      printf("o: %s\n",optarg);
      break;
    case 'l':
     printf("l: %s\n",optarg);
      break;
    case 's':
      printf("s: %s\n",optarg);
      break;
    case 'v':
      printf("s: %s\n",optarg);
      //showVersion();
      exit(0);
    case 'h':
      showUsage();
      exit(0);
    default:
      showUsage();
      exit(1);
    }
  }
  return 0;
}

本文链接: http://www.dtmao.cc/news_show_650128.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?