1. 程式人生 > >linux 輸入引數利用getopt、struct option、getopt_long、getopt_long_only解析

linux 輸入引數利用getopt、struct option、getopt_long、getopt_long_only解析

Linux 函式處理選項和引數

1、struct option 結構體

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.

2、關於長選項和短選項


GNU/Linux的命令列選項有兩種型別:短選項和長選項,前者以 '-' 作為前導符,後者以 '--' 作為前導符
例如:
process -a w --add -b --file a.txt b.txt - -- -e c.txt
含義如下:
a是短選項,帶一個引數vv;
add是長選項,無引數;
b是短選項,無引數;
file是長選項,帶一個引數a.txt;
b.txt是引數;
-是引數,通常表示標準輸入,stdin; 
--是一個指示符,表明停止掃描引數,其後所有部分都是引數,而不是選項;
-e是引數;

c.txt是引數

3、選項分析函式

	#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);

4、選項分析函式解析

1)getopt()函式,分析短選項

引數含義如下:

argc, argv是從main函式獲取的引數,原樣傳給getopt;argc記錄引數個數,包括函式名;argv儲存函式引數,包括函式名;
optstring為字串,指示如何分析引數。

關於optstring的幾點說明:
a、如果選項帶引數,該選項後接冒號,比如上例中optstring為"a:b",指示a帶引數,b沒有引數;
b、如果選項帶可選引數,該選項後接兩個冒號,比如"a::b",表明a可能有引數,也可能沒有;
c、如果optstring的開頭字元為':',表明如果指明選項帶引數,而實際命令列沒有引數時,getopt返回':'而不是'?'(預設情況下返回'?',和無法識別選項時返回一樣);
d、如果optstring的開頭字元為'+',表明一但遇到一個無選項的引數(指引數前面沒有選項),馬上停止掃描,隨後的部分當作引數來解釋;
e、如果optstring的開頭字元為'-',表明如果遇到無選項的引數,則把它當作選項1(不是字元'1')的引數(不是很明白)

f、該函式每解析完一個選項,就返回該選項字元。

g、如果選項帶引數,引數儲存在optarg中。如果選項帶可選引數,而實際無引數時,optarg為NULL。

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

i、當解析錯誤時,如果opterr為1則自動列印一條錯誤訊息(預設),否則不列印。

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

k、每當解析完一個argv,optind就會遞增。如果遇到無選項的引數,getopt預設會把該引數調後一位(本人理解應該是指標位置往後串),接著解析下一個引數(這裡的引數包括:選項、選項所帶的引數、無選項的引數,是個廣義的引數概念)。如果解析完成後還有無選項的引數,則optind指示的是第一個無選項的引數在argv中的索引。

2)getopt_long()函式,同時可以分析短選項和長選項

getopt_long的最後一個引數longindex在函式返回時指向被搜尋到的選項在longopts陣列中的下標。longindex可以為NULL,表明不需要返回這個值。

例子:

static const struct option lopts[] = {

{ "rtc", 1, 0, 'T'},
{ "rs485", 1, 0, '5'},
{ "spiw", 1, 0, 'S'},
{"capture", 1, 0, 'F'},
{"play", 1, 0, 'P'},
{"ipaddr", 1, 0, 'A'},
{ NULL, 0, 0, 0 }

}; //第三個成員最好填NULL,不填0

int c;
while(1){

c = getopt_long(argc, argv, "A:T:5:F:P:S", lopts, NULL);

if (c == -1)
break;

switch(c){

引數儲存在optarg中。。。

}

}

3)get_long_only()函式

getopt_long_only類似於getopt_long,但是它把'-'開頭的選項當作長選項來處理,一般情況下,這時結構體陣列變數longopts中也會包含我們想分析的短選項。

如果該選項與長選項不匹配,而與短選項匹配,則可以作為短選項解析。

在短選項找到的時候,getopt_long和getopt_long_only的表現和getopt一樣。如果長選項找到了,如果flag為 NULL,返回val,否則返回0。

錯誤情況的處理和getopt一樣,只是返回'?'時還可能是別的情況引起的:選項含糊不明確或者無關引數。

Comments SHELL程式設計如何解析命令列引數

問題描述:在linux shell中如何處理tail -n 10 access.log這樣的命令列選項?
在bash中,可以用以下三種方式來處理命令列引數,每種方式都有自己的應用場景。
1,直接處理,依次對$1,$2,...,$n進行解析,分別手工處理;
2,getopts來處理,單個字元選項的情況(如:-n 10 -f file.txt等選項);
3,getopt,可以處理單個字元選項,也可以處理長選項long-option(如:--prefix=/home等)。

總結:小指令碼手工處理即可,getopts能處理絕大多數的情況,getopt較複雜、功能也更強大。

1,直接手工處理位置引數
必須要要知道幾個變數,

複製程式碼程式碼如下:
   *    $0 :即命令本身,相當於c/c++中的argv[0]
    *    $1 :第一個引數.
    *    $2, $3, $4 ... :第2、3、4個引數,依次類推。
    *    $#  引數的個數,不包括命令本身
    *    [email protected] :引數本身的列表,也不包括命令本身
    *    $* :和[email protected]相同,但"$*" 和 "[email protected]"(加引號)並不同,"$*"將所有的引數解釋成一個字串,而"[email protected]"是一個引數陣列。

手工處理方式能滿足多數的簡單需求,配合shift使用也能構造出強大的功能,但處理複雜選項時建議用下面的兩種方法。
例子,(getargs.sh):

複製程式碼程式碼如下:
#!/bin/bash
if [ $# -lt 1 ]; then
    echo "error.. need args"
    exit 1
fi
echo "commond is $0"
echo "args are:"
for arg in "[email protected]"
do
    echo $arg
done

執行命令:

複製程式碼程式碼如下:
./getargs.sh 11 22 cc
commond is ./getargs.sh
args are:
11
22
cc

2,getopts (shell內建命令)
處理命令列引數是一個相似而又複雜的事情,為此,c提供了getopt/getopt_long等函式,c++的boost提供了options庫,在shell中,處理此事的是getopts和getopt。
getopts/getopt的區別,getopt是個外部binary檔案,而getopts是shell builtin。

複製程式碼程式碼如下:
[[email protected] ~]$ type getopt
getopt is /usr/bin/getopt
[[email protected] ~]$ type getopts
getopts is a shell builtin
getopts不能直接處理長的選項(如:--prefix=/home等)
關於getopts的使用方法,可以man bash  搜尋getopts
getopts有兩個引數,第一個引數是一個字串,包括字元和“:”,每一個字元都是一個有效的選項,如果字元後面帶有“:”,表示這個字元有自己的引數。getopts從命令中獲取這些引數,並且刪去了“-”,並將其賦值在第二個引數中,如果帶有自己引數,這個引數賦值在“optarg”中。提供getopts的shell內建了optarg這個變變,getopts修改了這個變數。
這裡變數$optarg儲存相應選項的引數,而$optind總是儲存原始$*中下一個要處理的元素位置。
while getopts ":a:bc" opt  #第一個冒號表示忽略錯誤;字元後面的冒號表示該選項必須有自己的引數
例子,(getopts.sh):

複製程式碼程式碼如下:
echo $*
while getopts ":a:bc" opt
do
        case $opt in
                a ) echo $optarg
                    echo $optind;;
                b ) echo "b $optind";;
                c ) echo "c $optind";;
                ? ) echo "error"
                    exit 1;;
        esac
done
echo $optind
shift $(($optind - 1))
#通過shift $(($optind - 1))的處理,$*中就只保留了除去選項內容的引數,可以在其後進行正常的shell程式設計處理了。
echo $0
echo $*

執行命令:

複製程式碼程式碼如下:
./getopts.sh -a 11 -b -c
-a 11 -b -c
11
3
b 4
c 5
5
./getopts.sh3,getopt(一個外部工具)
具體用用法可以 man getopt
#-o表示短選項,兩個冒號表示該選項有一個可選引數,可選引數必須緊貼選項,如-carg 而不能是-c arg
#--long表示長選項
例子,(getopt.sh):

複製程式碼程式碼如下:
#!/bin/bash
# a small example program for using the new getopt(1) program.
# this program will only work with bash(1)
# an similar program using the tcsh(1) script. language can be found
# as parse.tcsh
# example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# option a
# option c, no argument
# option c, argument `more'
# option b, argument ` very long '
# remaining arguments:
# --> `par1'
# --> `another arg'
# --> `wow!*\?'
# note that we use `"[email protected]"' to let each command-line parameter expand to a
# separate word. the quotes around `[email protected]' are essential!
# we need temp as the `eval set --' would nuke the return value of getopt.
#-o表示短選項,兩個冒號表示該選項有一個可選引數,可選引數必須緊貼選項
#如-carg 而不能是-c arg
#--long表示長選項
#"[email protected]"在上面解釋過
# -n:出錯時的資訊
# -- :舉一個例子比較好理解:
#我們要建立一個名字為 "-f"的目錄你會怎麼辦?
# mkdir -f #不成功,因為-f會被mkdir當作選項來解析,這時就可以使用
# mkdir -- -f 這樣-f就不會被作為選項。
temp=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
     -n 'example.bash' -- "[email protected]"`
if [ $? != 0 ] ; then echo "terminating..." >&2 ; exit 1 ; fi
# note the quotes around `$temp': they are essential!
#set 會重新排列引數的順序,也就是改變$1,$2...$n的值,這些值在getopt中重新排列過了
eval set -- "$temp"
#經過getopt的處理,下面處理具體選項。
while true ; do
        case "$1" in
                -a|--a-long) echo "option a" ; shift ;;
                -b|--b-long) echo "option b, argument \`$2'" ; shift 2 ;;
                -c|--c-long)
                        # c has an optional argument. as we are in quoted mode,
                        # an empty parameter will be generated if its optional
                        # argument is not found.
                        case "$2" in
                                "") echo "option c, no argument"; shift 2 ;;
                                *)  echo "option c, argument \`$2'" ; shift 2 ;;
                        esac ;;
                --) shift ; break ;;
                *) echo "internal error!" ; exit 1 ;;
        esac
done
echo "remaining arguments:"
for arg do
   echo '--> '"\`$arg'" ;
done
執行命令:
複製程式碼程式碼如下:
./getopt.sh --b-long abc -a -c33 remain
option b, argument `abc'
option a
option c, argument `33'
remaining arguments:
--> `remain'

4.用命令getopts,提供以下程式碼片段供參考:

#!/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"


相關推薦

linux 輸入引數利用getoptstruct optiongetopt_longgetopt_long_only解析

Linux 函式處理選項和引數1、struct option 結構體struct option { const char *name; int has_arg; int *flag; int val; };含義如下:name指明長選項的名稱;has_arg指明該選項是否帶引數

getoptgetopt_longgetopt_long_only解析命令列引數

一:posix約定:          下面是POSIX標準中關於程式名、引數的約定:          程式名不宜少於2個字元且不多於9個字元;          程式名應只包含小寫字母和阿拉伯數字;          選項名應該是單字元或單數字,且以短橫 ‘-’ 為

C# 利用函式反射XML序列化/反序列化儲存函式執行與輸入引數列表

最近在寫工業機械臂控制的程式碼,需要實現如下的一個功能: 將機械臂需要執行的函式與輸入引數按照順序儲存成檔案,載入檔案後能夠直接命令機械手進行動作。 介面使用winform進行開發。函式名與引數的儲存、載入的部分,考慮到日後函式的增刪,使用了函式反射+XML

Java的輸入和輸出if...else if...else判斷Java中列印陣列Java中陣列排序檢視函式方法的原始碼命令列引數

Java的輸入和輸出: 輸入: import java.util.Scanner Scanner s = new Scanner(System.in); //通過new Scanner(System.in)建立一個Scanner物件,控制檯會一直等待輸入,直到敲回車鍵

Linux程式設計》第三章(標準IO庫格式化輸入輸出檔案和目錄的維護掃描目錄)

標準IO庫 在啟動程式時,有三個檔案流是自動開啟的,分別是stdin,stdout,stderr。 1. fopen函式:用於檔案和終端的輸入和輸出。函式原型如下: #include <stdio.h> FILE *fopen(const char* f

Linux Shell(一):建立指令碼,變數字串陣列輸入輸出

0.建立一個Shell指令碼: vim abc.sh 1.首行宣告所使用的shell: #!/bin/bash #!是一個特殊的識別符號,其後,跟著解釋此指令碼的shell路徑。 bash只是shell的一種,還有很多其它shell,如:sh,csh,ksh,t

Linux命令引數前加---和不加-的區別

1.單- 和雙- -的區別 1.1 引數前單-表示後面引數為字元形式,如tar -zxvf; 1.2 引數前加- - 表示後面引數為單詞,如rm - -help; 2.加-和不加-的區別 在這裡插入程式

linux C語言編譯後執行檔案從命令輸入引數

linux使用gcc編譯C檔案後,會生成一個執行檔案,而我們執行這個檔案的時候想要使用輸入的引數怎麼辦呢,其實很簡單,我們在main函式中加入形參即可,如下圖 int main(int argc,cha

Linux Shell 程式設計 迴圈控制 條件控制 輸入引數

1. 傳入指令碼引數 $# 是傳給指令碼的引數個數  $0 是指令碼本身的名字  $1是傳遞給該shell指令碼的第一個引數  $2是傳遞給該shell指令碼的第二個引數  [email protected] 是傳給指令碼的所有引數的列表 2. 建立一個新檔案

linux核心引數tcp_syn_retriestcp_retries1和tcp_retries2的原始碼分析

enum { TCP_ESTABLISHED = 1, TCP_SYN_SENT, TCP_SYN_RECV, TCP_FIN_WAIT1, TCP_FIN_WAIT2, TCP_TIME_WAIT, TCP_CLOSE, TCP_CLOSE_WAIT,

Linux基礎:利用SSH上傳下載(使用sz與rz命令)

1、簡述   通常,利用SSH管理遠端Linux伺服器時,經常需要與本地互動檔案。當然,我們可以利用FTP方式,比如通過Filezilla客戶端軟體。不過直接使用SSH軟體(SecureCRT、Xshell)自帶的上傳和下載功能無疑使最方便快捷的。通常SSH軟體支援的檔

Linux時間引數atimectimemtime

在linux下每個檔案(目錄)都會記錄很多時間引數,主要有三個關於檔案變動的時間——mtime、atime、ctime,它們儲存與inode“資料結構”中,使用stat filename命令可以檢視它們。 1.ctime change time:當檔案(

利用C++ string實現任意長度小數整數之間的加法

code include spa ctype empty esp pac space temp 1 /* 2 大數的運算1--加法: 3 利用C++ string實現任意長度小數、整數之間的加法 4 作者:大大維 5 2017/5/5

利用jquery mobiscroll插件選擇日期selecttreeList的具體運用

order 移動 cancel fault ons val margin image ios mobiscroll是個很好用的用於移動端滑動選擇的插件,可以用來選擇日期,也可以用來選擇簡單選項或者一些復雜的樹形結構的選項,簡單分享下。 依賴也比較簡單,引入一個mob

linux就該這麽學-第4章 寫入轉義單引號別名全局變量

http ima src com 分享 全局變量 .com 文件 nbsp 一、寫入 1、> 清空寫入文件 2.>>追加寫入文件 3.2>>錯誤追加寫入文件 二、轉義 linux就該這麽學-第4章 寫入、轉義、單引號、別名、全局變量

linux下oracle11g R2的啟動與關閉監聽數據庫

source app var copy time lac started success let 一、啟動監聽與數據庫 1、啟動監聽: [html] view plain copy [[email protected]/* */ oracle]# s

Linux——信息分析(四)域名分析dighost

p地址 blog alt src org amt png 負責 一級域名 1、域名的命名格式為:WWW.<用戶名>.<二級域名>.<一級域名> dig www.baidu.com 解析過程說明

提供跟老男孩學Linux運維Shell編程實戰的第四第五章源代碼

linux shell 第四章是講Shell變量知識進階與實踐;第五章是講變量的數值計算實踐;附件中包括源碼,請下載。該兩章在學習時要註意相關事項:1.註意標點符號的使用:例如,單引號,反引號,雙引號等;2.註意該要留空格的留空格;3.註意特殊變量的作用;4.內置變量的使用;5.算術運算任的使用。本文

利用navicat創建存儲過程觸發器和使用遊標的簡單實例

.net fill student default hand 結果 alt 神奇 行記錄 原文鏈接 創建存儲過程和觸發器 1、建表 首先先建兩張表(users表和number表),具體設計如下圖: 2、存儲過程 寫一個存儲過程,往users表中插入數據,創建

#21 在Linux裏進程管理詳解,與pstreepspgreppkillpidoftop命令的應用

在linux裏進程管理詳解 與pstree、ps、pgrep、pkill、pidof、top命令的應用 進程管理: 所謂進程:process,一個活動的程序的實體的副本; 生命周期; 可能包含一個或多個執行流; 創建進程: 每個進程的組織結構是一致的: 內核在正常啟動並且全