要說$@與$*之前,需得先從shell script的positional parameter談起...我們都已經知道變量(variable)是如何定義及替換的,這個不用再多講了。但是,我們還需要知道有些變量是shell內定的,且其名稱是我們不能隨意修改的,其中就有positional parameter在內。
在shell script中,我們可用$0, $1, $2, $3 ...這樣的變量分別提取命令行中的如下部份:
script_name parameter1 parameter2 parameter3 ...
我們很容易就能猜出$0就是代表shell script名稱(路徑)本身,而$1就是其後的第一個參數,如此類推....
須得留意的是IFS的作用,也就是,若IFS被quoting處理後,那麼positional parameter也會改變。
如下例:
my.sh p1 "p2 p3" p4
由於在p2與p3之間的空格鍵被soft quote所關閉了,因此my.sh中的$2是"p2 p3"而$3則是p4 ...
還記得前兩章我們提到fucntion時,我不是說過它是script中的script嗎? ^_^
是的,function一樣可以讀取自己的(有別於script的) postitional parameter,惟一例外的是$0而已。
舉例而言:假設my.sh裏有一個fucntion叫my_fun ,若在script中跑my_fun fp1 fp2 fp3,那麼,function內的$0是my.sh,而$1則是fp1而非p1了...
不如寫個簡單的my.sh script 看看吧:
#!/bin/bash
my_fun() {
echo '$0 inside function is '$0
echo '$1 inside function is '$1
echo '$2 inside function is '$2
}
echo '$0 outside function is '$0
echo '$1 outside function is '$1
echo '$2 outside function is '$2
my_fun fp1 "fp2 fp3"
然後在command line中跑一下script就知道了:
chmod +x my.sh
./my.sh p1 "p2 p3"
$0 outside function is ./my.sh
$1 outside function is p1
$2 outside function is p2 p3
$0 inside function is ./my.sh
$1 inside function is fp1
$2 inside function is fp2 fp3
然而,在使用positional parameter的時候,我們要注意一些陷阱哦:
* $10不是替換第10個參數,而是替換第一個參數($1)然後再補一個0於其後!
也就是,my.sh one two three four five six seven eigth nine ten這樣的command line,my.sh裏的$10不是ten而是one0哦...小心小心!
要抓到ten的話,有兩種方法:
方法一是使用我們上一章介紹的${ },也就是用${10}即可。
方法二,就是shift了。
用通俗的說法來說,所謂的shift就是取消positional parameter中最左邊的參數( $0不受影響)。其默認值爲1,也就是shift或shift 1 都是取消$1,而原本的$2則變成$1、$3變成$2 ...若shift 3則是取消前面三個參數,也就是原本的$4將變成$1 ...
那,親愛的讀者,你說要shift掉多少個參數,纔可用$1取得${10}呢?^_^
okay,當我們對positional parameter有了基本概念之後,那再讓我們看看其它相關變量吧。
首先是$#:它可抓出positional parameter的數量。
以前面的my.sh p1 "p2 p3"爲例:
由於p2與p3之間的IFS是在soft quote中,因此$#可得到2的值。
但如果p2與p3沒有置於quoting中話,那$#就可得到3的值了。
同樣的道理在function中也是一樣的...
因此,我們常在shell script裏用如下方法測試script是否有讀進參數:
[ $# = 0 ]
假如爲0,那就表示script沒有參數,否則就是有帶參數...
接下來就是$@與$*:
精確來講,兩者只有在soft quote中才有差異,否則,都表示"全部參數"( $0除外)。
舉例來說好了:
若在command line上跑my.sh p1 "p2 p3" p4的話,
不管是$@還是$*,都可得到p1 p2 p3 p4就是了。
但是,如果置於soft quote中的話:
"$@"則可得到"p1" "p2 p3" "p4"這三個不同的詞段(word)﹔
"$*"則可得到"p1 p2 p3 p4"這一整串單一的詞段。
我們可修改一下前面的my.sh,使之內容如下:
#!/bin/bash
my_fun() {
echo "$#"
}
echo 'the number of parameter in "$@" is '$(my_fun "$@")
echo 'the number of parameter in "$*" is '$(my_fun "$*")
然後再執行./my.sh p1 "p2 p3" p4就知道$@與$*差在哪了...
the number of parameter in "$@" is3
the number of parameter in "$*" is1