1. 程式人生 > >getopt/getopts:Bash中命令列選項/引數處理

getopt/getopts:Bash中命令列選項/引數處理


本文轉載自:

http://www.cnblogs.com/FrankTan/archive/2010/03/01/1634516.html

--

0.引言


   寫程式的時候經常要處理命令列引數,本文描述在Bash下的命令列處理方式。

   選項與引數:

   如下一個命令列:
./test.sh -f config.conf -v --prefix=/home

   我們稱-f為選項,它需要一個引數,即config.conf, -v 也是一個選項,但它不需要引數。

   --prefix我們稱之為一個長選項,即選項本身多於一個字元,它也需要一個引數,用等號連線,當然等號不是必須的,/home可以直接寫在--prefix後面,即--prefix/home,更多的限制後面具體會講到。
   在bash中,可以用以下三種方式來處理命令列引數,每種方式都有自己的應用場景。

  • 手工處理方式
  • getopts
  • getopt

   下面我們依次討論這三種處理方式。

1. 手工處理方式


   在手工處理方式中,首先要知道幾個變數,還是以上面的命令列為例:
  • $0 : ./test.sh,即命令本身,相當於C/C++中的argv[0]
  • $1 : -f,第一個引數.
  • $2 : config.conf
  • $3, $4 ... :類推。
  • $#  引數的個數,不包括命令本身,上例中$#為4.
  • [email protected] :引數本身的列表,也不包括命令本身,如上例為 -f config.conf -v --prefix=/home
  • $* :和[email protected]相同,但"$*" 和 "[email protected]
    "(加引號)並不同,"$*"將所有的引數解釋成一個字串,而"[email protected]"是一個引數陣列。如下例所示:
#!/bin/bash
  
 for arg in "$*"
 do
    echo $arg
 done
  
 for arg in "[email protected]"
 do
    echo $arg
 done

執行./test.sh -f config.conf -n 10 會列印:

-f config.conf -n 10    #這是"$*"的輸出

#以下為[email protected]的輸出

-f 

config.conf
-n
10

所以,手工處理的方式即對這些變數的處理。因為手工處理高度依賴於你在命令列上所傳引數的位置,所以一般都只用來處理較簡單的引數。如

 “./test.sh 10”,而很少使用“./test -n 10”這種帶選項的方式。 典型用法為:
#!/bin/bash

#if [ -n "$1" ],引數不為空
if [ "$1" != "" ]
then
    #...有引數
else
then
    #...沒有引數
fi

手工處理方式能滿足大多數的簡單需求,配合shift使用也能構造出強大的功能,但在要處理複雜選項的時候建議用下面的兩種方法。

2. getopts/getopt

處理命令列引數是一個相似而又複雜的事情,為此,C提供了getopt/getopt_long等函式,C++的boost提供了Options庫,在shell中,處理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是獨立的可執行檔案,而getopts是由Bash內建的。先來看看引數傳遞的典型用法:
  • ./test.sh -a -b -c  : 短選項,各選項不需引數
  • ./test.sh -abc   : 短選項,和上一種方法的效果一樣,只是將所有的選項寫在一起。
  • ./test.sh -a args -b -c :短選項,其中-a需要引數,而-b -c不需引數。
  • ./test.sh --a-long=args --b-long :長選項
我們先來看getopts,它不支援長選項。使用getopts非常簡單:--test.sh
#!/bin/bash
#選項後面的冒號表示該選項需要引數
while getopts "a:bc" arg
do
        case $arg in
             a)
                #引數存在$OPTARG中
                echo "a's arg:$OPTARG" ;;
             b)
                echo "b" ;;
             c)
                echo "c" ;; 
             ?)
                #當有不認識的選項的時候arg為?
                echo "unkonw argument" exit 1 ;;
         esac
done
現在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc

來載入了。

應該說絕大多數指令碼使用該函式就可以了,如果需要支援長選項以及可選引數,那麼就需要使用getopt.下面是getopt自帶的一個例子:
#!/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


比如我們使用
./test -a  -b arg arg1 -c
你可以看到,命令列中多了個arg1引數,在經過getopt和set之後,命令列會變為:
-a -b arg -c -- arg1

$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1則被放到了最後。


3. 總結

豹尾。


相關推薦

getopt/getoptsBash命令選項/引數處理

本文轉載自: http://www.cnblogs.com/FrankTan/archive/2010/03/01/1634516.html -- 0.引言    寫程式的時候經常要處理命令列引數,本文描述在Bash下的命令列處理方式。    選項與引數:    如下

命令選項引數解析-getopt函式

在學習Unix/Linux程式設計實踐教程時,編寫練習一些linux命令,需要對命令列引數進行解析,從而接觸到getopt系列函式: 1. getopt() 2. getopt_long() 3.getopt_long_only() 總結如下: Parse c

Python命令選項引數解析策略

概述 在Python的專案開發過程中,我們有時需要為程式提供一些可以通過命令列進行呼叫的介面。不過,並不是直接使用 command + 當前檔案 就ok的,我們需要對其設定可選的各種各樣的操作型別。所以,這種情況下我們就有必要對傳入的引數進行解析操作。下面就此

shell指令碼使用getopts處理命令選項

在Linux系統中,許多命令都提供了選項,使用不同的選項就會得到不通的執行結果例如:ls命令,ls命令提供了多個選項:-l、-a、-A、-h、-i等等,每個選項具有不同的功能,我們自己寫指令碼時也可以定義選項,提示使用者如何使用,本文介紹如何使用getopts命令來處理命令選

命令選項解析函式(C語言)getopt()、getopt_long()和getopt_long_only

上午在看原始碼專案 webbench 時,剛開始就被一個似乎挺陌生函式 getopt_long() 給卡住了,說實話這函式沒怎麼見過,自然不知道這哥們是幹什麼的。於是乎百度了一番,原來是處理命令列選項引數的,的確,正規點的大型程式一般第一步就是處理命令列引數

Bash Shell命令選項/OA現金盤平臺租用

pre getopts 命令 描述 onf 列表 don 個數 相同 寫程序的時候經常要處理命令行參數,本文描述在Bash下的命令行處理方式。 選項與參數: OA現金盤平臺租用(企 娥:217 1793 408) 如下一個命令行: . / test.sh - f con

GithubGIT BASH基礎命令

GITHUB中GIT BASH基礎命令列 原文 : https://www.cnblogs.com/WangXinPeng/p/8016293.html 今天來講一下關於github命令列相關知識。呵呵,其實github都沒太明白就把git bash擺上來當道菜。看來,我有當程式設

centos升級gcc到4.8.2(cc1plus: 錯誤無法識別的命令選項“-std=c++11”)

驗證:gcc -v;或者g++ -v,如果顯示的gcc版本仍是以前的版本,就需要重啟系統;或者可以檢視gcc的安裝位置:which gcc;然後在檢視版本 /usr/local/bin/gcc -v,通常gcc都安裝在該處位置

argparse解析命令選項

argparse模組 在每個 add_argument() 呼叫中,dest 引數指定解析結果被指派給屬性的名字。 metavar 引數被用來生成幫助資訊。action 引數指定跟屬性對應的處理邏輯, 通常的值為 store ,被用來儲存某個值或將多個引數值收集

使用 getopt 處理命令引數(長選項

getopt命令並不是bash的內建命令,它是由util-linux包提供的外部命令。 getopt 與 getopts 的區別 getopts 是 shell 內建命令, getopt 是一個獨

main:處理命令選項

有時我們需要給main函式傳遞實參, 我們可以把命令列選項通過兩個形參傳遞給main函式: int mian(int argc, char *argv[]) { ... }; argv是argument value,是一個數組,它的元素是指向C風格字串的指標;第一個形參argc是argument coun

CCF Python題解(100分)201403-3 命令選項

CCF Python題解(100分)201403-3 命令列選項 form = input() n = int(input()) def judge(str3): flag = True for k in str3: if not (k.islower

201403-3命令選項(c++,字串處理

試題編號: 201403-3 試題名稱: 命令列選項 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問

pytest 常用命令選項(二)

  本文接上篇繼續簡介pytest常用的命令列選項。   8、-v(--verbose) 選項     使用-v/--verbose選項,輸出的資訊會更詳細。最明顯的區別就是每個檔案中的每個測試用例都佔一行,測試的名字和結果都會顯示出來,而不僅僅是一個點或字元。如下圖:      

argparse - 命令選項引數解析

閱讀原文點我 argparse模組作為optparse的一個替代被新增到Python2.7。argparse的實現支援一些不易於新增到optparse以及要求向後不相容API變化的特性,因此以一個新模組新增到標準庫。 與optparse相比較 argparse的API類似於optpars

VS--解決D8016“/ZI”和“/Gy-”命令選項不相容的問題

    GL為全程優化,在配置屬性->C/C++ ->優化->全程優化中設定,而ZI編譯生成除錯資訊,在配置屬性->C/C++ ->常規->除錯資訊格式中設定。如編譯debug版本,則去掉 GL選項(將全程優化中選為

CCF-201403-3-命令選項

第三題一如既往的是模擬題,這次模擬解釋命令列。做第三題的心態就是:不要被題目嚇到,不用急,慢慢看完就好,最後注意細節。這一題規則很清晰,難度適中。 題目大意 給一個格式化字串(每個字母是一個選項),再給出幾個命令列,看每個命令列裡面哪些選項符合就輸出哪些,遇到不符合的就結束分析

kettle命令執行轉換或者作業

很多時候,我們都會講做好的kettle轉換或者作業放到linux伺服器執行,基於linux沒有圖形介面,所以此時用命令列是必要的了。 一、windows下cmd執行方式: 首先說一下windows下如何執行,算是一個回顧吧: 找到kettle安裝目錄,在目錄下直接cmd可以進入該目錄

201412-3 命令選項

1、用兩個布林陣列來儲存選項及其是否帶參 2、遍歷命令列的時候,用正則匹配每個字元是否匹配選項或引數的規則,然後檢視是否存在該選項。出現的選項及其引數用TreeMap儲存,因為treemap可以對key進行排序,正好是題目要求的輸出。 奉上java滿分程式碼 import java.ut

命令選項(0分....)

emmmmm,,,不知道哪兒沒考慮到.......改了好多次...  #include <iostream> #include <cstdio> #include <map> #include <cstring> #include &