getopt();getopt_long();getopt_long_only();option

轉自http://blog.csdn.net/vblittleboy/article/details/6544285,感謝博主分享


如何分析命令行參數


Sun, 2006-07-16 01:27 — Marchday

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,還有幾點說明:
如果選項帶參數,該選項後接冒號,比如上例中optstring爲"a:b",指示a帶參數,b沒有參數;
如果選項帶可選參數,該選項後接兩個冒號,比如"a::b",表明a可能有參數,也可能沒有;
如果optstring的開頭字符爲':',表明如果指明選項帶參數,而實際命令行沒有參數時,getopt返回':'而不是'?'(默認情況下返回'?',和無法識別的參數返回一樣);
如果optstring的開頭字符爲'+',表明一但遇到一個無選項參數,馬上停止掃描,隨後的部分當作參數來解釋;
如果optstring的開頭字符爲'-',表明如果遇到無選項參數,則把它當作選項1(不是字符'1')的參數

該函數每解析完一個選項,就返回該選項字符。

如果選項帶參數,參數保存在optarg中。如果選項帶可選參數,而實際無參數時,optarg爲NULL。

當遇到一個不在optstring指明的選項時,返回字符‘?’。如果在optstring指明某選項帶參數而實際沒有參數時,返回字符‘?’或者字符‘:’,視optstring的第一個字符而定。這兩種情況選項的實際值被保存在optopt中。

當解析錯誤時,如果opterr爲1則自動打印一條錯誤消息(默認),否則不打印。

當解析完成時,返回-1。

每當解析完一個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 ’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 (0);
       }

我們用digit_optind和this_option_optind來跟蹤選項012是否在一起,比如選項 -012 和-0 -1 -2 的optind情況是不一樣的,前者返回0、1、2時optind相同,而後者optind的值依次大1。


Comments

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"

發佈了19 篇原創文章 · 獲贊 14 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章