SHELL十三问之九:$@ 与 $* 差在哪?

要说$@$*之前,需得先从shell scriptpositional parameter谈起...我们都已经知道变量(variable)是如何定义及替换的,这个不用再多讲了。但是,我们还需要知道有些变量是shell内定的,且其名称是我们不能随意修改的,其中就有positional parameter在内。BSD爱好者乐园(v5C f mS;bPGF

KBH qV-L4fg
shell script中,我们可用$0, $1, $2, $3 ...这样的变量分别提取命令行中的如下部份:BSD爱好者乐园:{5o|~)kZ2e

script_name parameter1 parameter2 parameter3 ...

C4m9eH {HC

我们很容易就能猜出$0就是代表shell script名称(路径)本身,而$1就是其后的第一个参数,如此类推....BSD爱好者乐园5yoG,~{-G4H
须得留意的是IFS的作用,也就是,若IFSquoting处理后,那么positional parameter也会改变。

#of/q IJ ZxA
如下例:

S}1RS1srG3Y

my.sh p1 "p2 p3" p4

%F I:x,p(Z

由于在p2p3之间的空格键被soft quote所关闭了,因此my.sh中的$2"p2 p3"$3则是p4 ...BSD爱好者乐园r3TW�N�m/sJ,c%`
BSD爱好者乐园?#?OQ,~#Sm#m#i
还记得前两章我们提到fucntion时,我不是说过它是script中的script吗?
  ^_^
/r'j+yV(G�Kj,Ue*V,Li
是的,function一样可以读取自己的(有别于script) postitional parameter,惟一例外的是$0而已。
BSD爱好者乐园$dhD il
举例而言:假设my.sh里有一个fucntionmy_fun ,若在script中跑my_fun fp1 fp2 fp3,那么,function内的$0my.sh,而$1则是fp1而非p1...
V /Ch;QBSD爱好者乐园VEI5}A
不如写个简单的my.sh script  看看吧:
BSD爱好者乐园-}6ISa8m�j-X

#!/bin/bashBSD爱好者乐园%x t AJ9W
BSD爱好者乐园{&]Ws nBS'h�e;K%V
my_fun() {
6]#H*G1G&@a.y$q5ig    echo '$0 inside function is '$0
q8rP;v.O    echo '$1 inside function is '$1
,c]M {-A3/ P5t1D&us    echo '$2 inside function is '$2
3R%FXW q(GGr}BSD爱好者乐园J ^n.P!^7SW;K

+Z(jr!lkAecho '$0 outside function is '$0
}*O)n.z"q)f*J/wecho '$1 outside function is '$1BSD爱好者乐园Wk#f2jMZ*m2t'U
echo '$2 outside function is '$2BSD爱好者乐园8/2_zi+gG ]

:l'~ Ja&pmy_fun fp1 "fp2 fp3"

{"JP.k[w0OF0f

然后在command line中跑一下script就知道了:BSD爱好者乐园#q{2c�T'^ v4R5GP2oa

chmod +x my.shBSD爱好者乐园 f;F'I$^w
./my.sh p1 "p2 p3"
6WL_7}u7w)Ji$0 outside function is ./my.shBSD爱好者乐园9N D{)D'e9f"P
$1 outside function is p1BSD爱好者乐园!IY#j(DZQY/qZ+v
$2 outside function is p2 p3BSD爱好者乐园OL[}dr,P4W5X&j-[2P
$0 inside function is ./my.shBSD爱好者乐园3J o8g*~ S7^)x |
$1 inside function is fp1
)xlVstz$2 inside function is fp2 fp3

8xy(Jbh6E2LRjQ

然而,在使用positional parameter的时候,我们要注意一些陷阱哦:BSD爱好者乐园7e Bt`0r;n p
* $10不是替换第10个参数,而是替换第一个参数($1)然后再补一个0于其后!
$q4dU^e pTR3~_
也就是,my.sh one two three four five six seven eigth nine ten这样的command linemy.sh里的$10不是ten而是one0...小心小心!BSD爱好者乐园i0SJ:`6A~
要抓到ten的话,有两种方法:
U rIT0o5{BSD爱好者乐园*IE/s g s+d
方法一是使用我们上一章介绍的${ },也就是用${10}即可。
n p!RHjRBSD爱好者乐园e#Mb+W%n&}A
方法二,就是shift了。
"aZKyt-v4L_
用通俗的说法来说,所谓的shift就是取消positional parameter中最左边的参数( $0不受影响)。其默认值为1,也就是shiftshift 1  都是取消$1,而原本的$2则变成$1$3变成$2 ...shift 3则是取消前面三个参数,也就是原本的$4将变成$1 ...
E;R.b#R&{2s7P-v
那,亲爱的读者,你说要shift掉多少个参数,才可用$1取得${10}呢?
^_^BSD爱好者乐园{/L `%{d%_+uLvj�^
BSD爱好者乐园-G/w8T0K$^4^2}{
okay
,当我们对positional parameter有了基本概念之后,那再让我们看看其它相关变量吧。

0H)w'B(AT#/:iS
首先是$#:它可抓出positional parameter的数量。
/[Nct1x4pl-S]Z w
以前面的my.sh p1 "p2 p3"为例:BSD爱好者乐园/C5eKC5FH O9ni
由于p2p3之间的IFS是在soft quote中,因此$#可得到2的值。BSD爱好者乐园8M"p L'a�V/a
但如果p2p3没有置于quoting中话,那$#就可得到3的值了。BSD爱好者乐园xC%[1u'x:A|$x
同样的道理在function中也是一样的...BSD爱好者乐园*{_mn)] NV3C`
BSD爱好者乐园/%q1|�v$L~(X?
因此,我们常在shell script里用如下方法测试script是否有读进参数:

-V~#| DtbE+s

 [ $# = 0 ]BSD爱好者乐园G Vs7J ~

假如为0,那就表示script没有参数,否则就是有带参数...BSD爱好者乐园p,_�xf t_0Rd

3RQ8p}�tT'U7i$h:q
接下来就是$@$*
BSD爱好者乐园 c+A)H*}#j7?
精确来讲,两者只有在soft quote中才有差异,否则,都表示"全部参数"( $0除外)
N'[@'Xwz8B ?b*Bi
举例来说好了:BSD爱好者乐园A zWl3K
若在command line上跑my.sh p1 "p2 p3" p4的话,
O6P#?'Rf(Y8I
不管是$@还是$*,都可得到p1 p2 p3 p4就是了。
bf(~'V({z
但是,如果置于soft quote中的话:
w,T~X t/Il"$@"
则可得到"p1" "p2 p3" "p4"这三个不同的词段(word)
n7sj/%q~4yO"$*"
则可得到"p1 p2 p3 p4"这一整串单一的词段。
yG7X@H9M
}cr0f D0Grf
我们可修改一下前面的my.sh,使之内容如下:

]|&]3NCD;j{ P {

#!/bin/bash
5qBTB)[{B {kBSD爱好者乐园8nL7e^)`BqVt
my_fun() {BSD爱好者乐园6of)KDz?,R
    echo "$#"
9@v;GM6Zxz+/M0?}
S T^K-}/)v
'Bg!L"Ol+]1|,gecho 'the number of parameter in "$@" is '$(my_fun "$@")
JB*TXow.F3Wecho 'the number of parameter in "$*" is '$(my_fun "$*")

y.dz%K_Hv3z3?

然后再执行./my.sh p1 "p2 p3" p4就知道$@$*差在哪了... 

}b;SGMI.m

the number of parameter in "$@" is3BSD爱好者乐园2x$CK#A0L%D

the number of parameter in "$*" is1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值