寫了一個shell腳本,需要向shell腳本中傳參數供腳本使用,達到的效果是傳的參數可以是可選參數
下面是一個常規化的shell腳本:
echo "執行的文件名為: $0"; echo "第一個參數名為: $1"; echo "第二個參數名為: $2"
正常的向shell腳本中傳參數的方法為:
./test.sh 1 2 3
最后執行的結果為:
執行的文件名為: ./test.sh 第一個參數名為: 1 第二個參數名為: 2
但是這個是只能按照順序傳遞參數,並且不能傳遞可選參數,然后查資料,發現了一個shell的getopts 用法
首先貼個例子
[hello@Git shell]$ bash test.sh -a hello this is -a the arg is ! hello [hello@Git shell]$ more test.sh #!/bin/bash while getopts "a:" opt; do case $opt in a) echo "this is -a the arg is ! $OPTARG" ;; \?) echo "Invalid option: -$OPTARG" ;; esac done
getopts一共有兩個參數,第一個是-a這樣的選項,第二個參數是 hello這樣的參數。
選項之間可以通過冒號:進行分隔,也可以直接相連接,:表示選項后面必須帶有參數,如果沒有可以不加實際值進行傳遞
例如:getopts ahfvc: option表明選項a、h、f、v可以不加實際值進行傳遞,而選項c必須取值。使用選項取值時,必須使用變量OPTARG保存該值。
[hello@Git shell]$ bash test.sh -a hello -b this is -a the arg is ! hello test.sh: option requires an argument -- b Invalid option: - [hello@Git shell]$ bash test.sh -a hello -b hello -c this is -a the arg is ! hello this is -b the arg is ! hello this is -c the arg is ! [hello@Git shell]$ more test.sh #!/bin/bash while getopts "a:b:cdef" opt; do case $opt in a) echo "this is -a the arg is ! $OPTARG" ;; b) echo "this is -b the arg is ! $OPTARG" ;; c) echo "this is -c the arg is ! $OPTARG" ;; \?) echo "Invalid option: -$OPTARG" ;; esac done [hello@Git shell]$
執行結果結合代碼顯而易見。同樣你也會看到有些代碼在a的前面也會有冒號,比如下面的
情況一,沒有冒號:
[hello@Git shell]$ bash test.sh -a hello this is -a the arg is ! hello [hello@Git shell]$ bash test.sh -a test.sh: option requires an argument -- a Invalid option: - [hello@Git shell]$ more test.sh #!/bin/bash while getopts "a:" opt; do case $opt in a) echo "this is -a the arg is ! $OPTARG" ;; \?) echo "Invalid option: -$OPTARG" ;; esac done [hello@Git shell]$
情況二,有冒號:
[hello@Git shell]$ bash test.sh -a hello this is -a the arg is ! hello [hello@Git shell]$ bash test.sh -a [hello@Git shell]$ more test.sh #!/bin/bash while getopts ":a:" opt; do case $opt in a) echo "this is -a the arg is ! $OPTARG" ;; \?) echo "Invalid option: -$OPTARG" ;; esac done
情況一輸入 -a 但是后面沒有參數的的時候,會報錯誤,但是如果像情況二那樣就不會報錯誤了,會被忽略。
while getopts ":a:bc" opt #第一個冒號表示忽略錯誤;字符后面的冒號表示該選項必須有自己的參數
參考 https://blog.csdn.net/xluren/article/details/17489667
但是這樣還是無法滿足可以輸入可選參數的要求,這樣輸入的參數名稱也是固定的,參數的數量也是固定的,然后接下來了解了shell 的getopt用法。
看過官方文檔后,自己寫了個小demo
#!/bin/bash #獲取對應的參數 沒有的話賦默認值 ARGS=`getopt -o a::b::l::n::t::p:: --long along::,blong::,llong::,plong:: -n 'example.sh' -- "$@"` if [ $? != 0 ]; then echo "Terminating..." exit 1 fi #echo $ARGS #將規范化后的命令行參數分配至位置參數($1,$2,...) eval set -- "${ARGS}" while true; do case "$1" in -a|--along) case "$2" in "") project1_name=master; shift 2; ;; *) project1_name=$2; shift 2; ;; esac ;; -b|--blong) case "$2" in "") project2_name=master; shift 2 ;; *) project2_name=$2; shift 2; ;; esac ;; -l|--llong) case "$2" in "") layer=layer_1; shift 2 ;; *) layer=$2; shift 2; ;; esac ;; -n) case "$2" in "") number=1000; shift 2 ;; *) number=$2; shift 2; ;; esac ;; -t) case "$2" in "") select_type=top; shift 2 ;; *) select_type=$2; shift 2; ;; esac ;; -p) case "$2" in "") data_point=; shift 2 ;; *) data_point=$2; shift 2; ;; esac ;; --) shift break ;; *) echo "Internal error!" exit 1 ;; esac done project1_name=${project1_name:-master} project2_name=${project2_name:-master} layer=${layer:-layer_1} number=${number:-100} select_type=${select_type:-top} data_point=${data_point:-}
這一部分為輸入參數對應的字符
a::b::l::n::t::p::
#-o表示短選項,兩個冒號表示該選項有一個可選參數,可選參數必須緊貼選項,如-carg 而不能是-c arg
#--long表示長選項
一目了然,首先是根據傳遞過來的 是 -a 還是 -b -l 進行判斷,如果只有-a后面沒有參數的話 則賦默認值,同時在
project1_name=${project1_name:-master}
project2_name=${project2_name:-master}
layer=${layer:-layer_1}
number=${number:-100}
select_type=${select_type:-top}
data_point=${data_point:-}
這一步 也進行了默認值的賦值操作。如果上面沒有 project1_name 則賦值為master
例子如下:
參數的默認值設置 $cat myscript.sh print ${1:-hello} print ${2:-kshell} $sh myscript.sh hello kshell
