要說 $@與 $* 之前, 需得先從 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 quoting 所關閉了, 因此,my.sh 的中 $2 是 "p2 p3", 而 $3 則是 p4...
還記得前兩章,我們提到 function 時, 我們不是說過,它是 script 中的 script 嗎?^_^
是的,function 一樣可以讀取自己的 (有別于 script 的) positional parameter, 唯一例外的是 $0 而已。
舉例而言: 假設 my.sh 里有一個函數 (function) 叫 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 755 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 個參數, 而是替換第一個參數,然后在補一個 0 于其后;
也就是說, my.sh one two three four five six seven eight nine ten 這樣的 command line, my.sh 里的 $10 不是 ten 而是 one0 哦... 小心小心 要抓到 ten 的話,有兩種方法:
方法一:使用我們上一章介紹的 ${}, 也就是用 ${10} 即可。
用通俗的說法來說, 所謂的 shift 就是取消 positional parameter 中最左邊的參數 ($0 不受影響)。 其預設值為 1,也就是 shift 或 shift 1 都是取消 $1, 而原本的 $2 則變成 $1, $3 則變成 $2... 那親愛的讀者,你說要 shift 掉多少個參數, 才可用 $1 取得到 ${10} 呢? ^_^
okay,當我們對 positional parameter 有了基本的概念之后, 那再讓我們看看其他相關變量吧。
先是 $#, 它可抓出 positional parameter 的數量。 以前面的my.sh p1 "p2 p3"為例: 由于 "p2 p3" 之間的IFS是在 soft quote 中, 因此,$# 就可得到的值是 2. 但如果 p2 與 p3 沒有置于 quoting 中話, 那 $# 就可得到 3 的值了。 同樣的規(guī)則,在 function 中也是一樣。
因此,我們常在 shell script 里用如下方法, 測試 script 是否有讀進參數:
[ $# = 0 ]
假如為 0, 那就表示 script 沒有參數,否則就是帶有參數...
接下來就是 *$@與 $: 精確來講,兩者只有在 soft quote 中才有差異, 否則,都表示 “全部參數” ($0 除外)**。
若在 comamnd line 上, 跑·my.sh p1 "p2 p3" p4·的話, 不管 $@還是 $*, 都可得到 p1 p2 p3 p4 就是了。
但是,如果置于 soft quote 中的話:
我們修改一下前面的 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 "$*")
然后再執(zhí)行:
./my.sh p1 "p2 p3" p4
就知道,$@與 $* 差在哪了... ^_^