要说$@与$*之前,需要先从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…

还记得前两章我们提到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中跑一下就知道了:

$ 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}呢?

Ok,当我们对positional parameter(位置参数)有了基本概念之后,那再让我们看看其他相关变量吧。

首先是$#:他可获取positional parameter(位置参数)的数量。

以前面的my.sh p1 “p2 p3″为例:

由于p2与p3之间的IFS是在soft quote(软引用)中,因此$#可得到2的值。

但如果p2与p3没有置于引用中的话,那$#就可得到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 就知道 $@ 与 $* 差在哪了 … ^_^

$ bash my.sh p1 "p2 p3" p4
the number of parameter in "$@" is 3
the number of parameter in "$*" is 1

转载请注明:知识蚂蚁 » shell十三问?(简体中文版)第9问:$@与$*差在哪?

我来说说

(便于我们更好的交流)

有不明白的地方欢迎留言哦~
取消