SHELL十三問之五:var=value?export 前後差在哪?

這次讓我們暫時丟開command line,先來了解一下bash變量(variable)...
?d ]0[-eL9V"n1
;W�E r%l.U#z3i&D1
所謂的變量,就是就是利用一個特定的"名稱"(name)來存取一段可以變化的""(value)BSD愛好者樂園'lt0` c@)R#u
BSD愛好者樂園#e0LR%N3uV,{p
*設定(set)*
W*/B'x+M�F5y6D d1
bash中,你可以用"="來設定或重新定義變量的內容:BSD愛好者樂園#J8E7ot%AFBp,`,J9F H6Mf
        name=value
6YK$u!|m1
在設定變量的時侯,得遵守如下規則:
-S9U Id-_x(OJy1        *
等號左右兩邊不能使用區隔符號(IFS),也應避免使用shell的保留字符(meta charactor)BSD愛好者樂園w2F"R%S Q#},M[x|q
        *
變量名稱不能使用$符號。
%Qp)}j$NLm1        *
變量名稱的第一個字母不能是數字(number)
"r0pQdXu@%H x*L1        *
變量名稱長度不可超過256個字母。BSD愛好者樂園 C IV7Hle
        *
變量名稱及變量值之大小寫是有區別的(case sensitive)BSD愛好者樂園mWj3P5N m`Jy`

#bZu7Idy:y.u1
如下是一些變量設定時常見的錯誤:BSD愛好者樂園A2[otf L
        A= B       
:不能有IFS
3@U(I_l(S1        1A=B       
:不能以數字開頭BSD愛好者樂園F+R+[i"})Y]"SUaJ%s
        $A=B       
:名稱不能有$
sH$^:o'q N ^9s-U1        a=B       
:這跟a=b是不同的
yA�MR f1
如下則是可以接受的設定:
GkT8~3E0Nko/@"V,ds1        A=" B"       
IFS被關閉了(請參考前面的quoting章節)BSD愛好者樂園'p)[#@!q'U.q
        A1=B       
:並非以數字開頭
1O3O6N ?H1?V@ g1t(`0G1        A=$B       
$可用在變量值內
f bWVk0c&OP(_/Y9m1        This_Is_A_Long_Name=b       
:可用_連接較長的名稱或值,且大小寫有別。BSD愛好者樂園tdde t&D

-_ t-`6m?P1Jr1
*變量替換(substitution)*
m/bf"mRW2| H1z1
Shell之所以強大,其中的一個因素是它可以在命令行中對變量作替換(substitution)處理。BSD愛好者樂園RMJan6b�w9I�o
在命令行中使用者可以使用$符號加上變量名稱(除了在用=號定義變量名稱之外)BSD愛好者樂園`9om PV;f
將變量值給替換出來,然後再重新組建命令行。
7sJAoKqD#CPY1
比方:

!/(F ^OX Ppf~5@1

        $ A=ls
h6P1FC%]1        $ B=laBSD愛好者樂園7B@EP2Z
        $ C=/tmpBSD愛好者樂園F*s3i%P|%To ?
        $ $A -$B $C
BSD愛好者樂園C{/A$W-h@

(注意:以上命令行的第一個$shell prompt,並不在命令行之內。)BSD愛好者樂園 FS+{V�RefKI}
必需強調的是,我們所提的變量替換,只發生在command line上面。(是的,讓我們再回到command line吧﹗)
A6N5e2eQ4H'OR^1
仔細分析最後那行command line,不難發現在被執行之前(在輸入CR字符之前)BSD愛好者樂園:[@:q9y/&^%b!M*P
$
符號會對每一個變量作替換處理(將變量值替換出來再重組命令行),最後會得出如下命令行:

)|'V{5K|$|1

        ls -la /tmpBSD愛好者樂園 }z3[l3~1p$?(y3]:E

還記得第二章我請大家"務必理解"的那兩句嗎?若你忘了,那我這裏再重貼一遍:BSD愛好者樂園+AR�yc {jw4Vy

若從技術細節來看,shell會依據IFS(Internal Field Seperator)command line所輸入的文字給拆解爲"字段"(word)BSD愛好者樂園u8i }-_'D nm$iS
然後再針對特殊字符(meta)先作處理,最後再重組整行command line

n)y{]]*i1

這裏的$就是command line中最經典的meta之一了,就是作變量替換的﹗
tav4KQ1
在日常的shell操作中,我們常會使用echo命令來查看特定變量的值,例如:BSD愛好者樂園6[V~`W6QUH

        $ echo $A -$B $CBSD愛好者樂園%Liqj'R

我們已學過,echo命令只單純將其argument送至"標準輸出"(STDOUT,通常是我們的熒幕)
/v1xcm$KEin0~1
所以上面的命令會在熒幕上得到如下結果:

RWWWu8n._ D1

        ls -la /tmp

d,ViB'Fp3y1

這是由於echo命令在執行時,會先將$A(ls)$B(la)、跟$C(/tmp)給替換出來的結果。
Tc c&nVa1
C0^W4_Y0]:w.~5y!t _1
利用shell對變量的替換處理能力,我們在設定變量時就更爲靈活了:
Hb8B*lU6J3~2L1        A=BBSD愛好者樂園j Mp(p5FeE6r0p
        B=$ABSD愛好者樂園)nKNGsw._
這樣,B的變量值就可繼承A變量"當時"的變量值了。
N:dP| p g1
不過,不要以"數學羅輯"來套用變量的設定,比方說:BSD愛好者樂園/fq3~Y;p3GI |hxdW
        A=B
?]4uL;v c/l7F1        B=C
"C*n:M"Q#O�{"?Q(id-[E1
這樣並不會讓A的變量值變成C
L./%?.d(B1
上面是單純定義了兩個不同名稱的變量:A  B,它們的值分別是B  C。再如:BSD愛好者樂園�r;qDa!{&Fnp2flC
        A=BBSD愛好者樂園F-AA*U^'@%M+` s
        B=$ABSD愛好者樂園�/9t!oB}@wmRyO
        A=C
X H*Q/U |q tl T1
同樣也不會讓B的值換成CBSD愛好者樂園.y9Y'v7EHhvB
 
2h#dsO-{"@9O9PDc*z1
若變量被重複定義的話,則原有舊值將被新值所取代。(這不正是"可變的量"嗎?  ^_^)BSD愛好者樂園g4{cr%Ap
當我們在設定變量的時侯,請記着這點:BSD愛好者樂園1x KO ~)n
        *用一個名稱儲存一個數值
3I.x�?I�Z�r1
僅此而已。BSD愛好者樂園0R,t-F:P9C/m-Q m
BSD愛好者樂園 U$B[(Z,qd%/5s
此外,我們也可利用命令行的變量替換能力來"擴充"(append)變量值:
Ble"E^~g1        A=B:C:D
:I&L3s:bqqY2d2l1        A=$A:E
[ Mqri:u D%eIM1
這樣,第一行我們設定A的值爲"B:C:D",然後,第二行再將值擴充爲"A:B:C:E"BSD愛好者樂園%a@Y(@9a @
BSD愛好者樂園_;a1N { Wd
上面的擴充範例,我們使用區隔符號( : )來達到擴充目的,
MM1W`k*@:G&Sdpn1
要是沒有區隔符號的話,如下是有問題的:
]n P;D6A5Cb;B1        A=BCDBSD愛好者樂園6tvH7q-A9a&qD|N(DG
        A=$AEBSD愛好者樂園 S4Z pP`$w
因爲第二次是將A的值繼承$AE的提換結果,而非$A再加EBSD愛好者樂園%yD$np']V TP:/
要解決此問題,我們可用更嚴謹的替換處理:BSD愛好者樂園'z9[PO`0hI
        A=BCD
:d!jO'bb /"T1        A=${A}E
2u1at'H-Pc1
上例中,我們使用{}將變量名稱的範圍給明確定義出來,BSD愛好者樂園1I9UrauK5[}I�Q
如此一來,我們就可以將A的變量值從BCD給擴充爲BCDEBSD愛好者樂園.@4Ie�|3{'W[ G_r

SD+Tz2w1(
提示:關於${name}事實上還可做到更多的變量處理能力,這些均屬於比較進階的變量處理,現階段暫時不介紹了,請大家自行參考數據。如CU的貼子:BSD愛好者樂園[s6]#l7D-RiBY
http://www.chinaunix.net/forum/viewtopic.php?t=201843)BSD愛好者樂園 Mi*w)Yd `T

u4r SqM/Ab#X1
* export *BSD愛好者樂園 s;o7J$y8WU:RRP

G7C[7Y` zAQ O$UT1
嚴格來說,我們在當前shell中所定義的變量,均屬於"本地變量"(local variable)
8Gc2_2c U-E1
只有經過export命令的"輸出"處理,才能成爲環境變量(environment variable)

4aW6IE)M1

        $ A=BBSD愛好者樂園 UH3X x:@2GR}
        $ export A
BSD愛好者樂園%}�?#u7t#U2L)P

或:

Q G:k(kN4T;z'z1

        $ export A=B

|X z ]/c+L(]i3n1

經過export輸出處理之後,變量A就能成爲一個環境變量供其後的命令使用。
GO1t(v8}f9`1
在使用export  的時侯,請別忘記shell在命令行對變量的"替換"(substitution)處理,BSD愛好者樂園4kqNL{*h&LJ#m
比方說:

^ss ]8l1

        $ A=B
o�T%{m*p{1        $ B=CBSD愛好者樂園{f9z;Ngh8C-Y3W{
        $ export $A

M#`&}6B1G Gg^$Wr1

上面的命令並未將A輸出爲環境變量,而是將B作輸出,BSD愛好者樂園E#K3I4r6c5h
這是因爲在這個命令行中,$A會首先被提換出B然後再"塞回"export的參數。
:IZ6s�B Y`A"~1
0/;|{(bg wb"^&^4R1
要理解這個export,事實上需要從process的角度來理解才能透徹。
6n/nJ2n1
我將於下一章爲大家說明process的觀念,敬請留意。BSD愛好者樂園K6/ o @6Rh{
BSD愛好者樂園6f0a!Hmhx/
*取消變量*BSD愛好者樂園Uaz_P_DjJ

NYy e&r0[1
要取消一個變量,在bash中可使用unset命令來處理:

7{,qZ oS&t)|0C ?5M1

        unset A

x1~aW{+v)b1

export一樣,unset命令行也同樣會作變量替換(這其實就是shell的功能之一)BSD愛好者樂園V2i9ToG
因此:

@ {FZfqR,j1

        $ A=BBSD愛好者樂園1W:T2teDQ3V
        $ B=C
@i&x1W])f ~~cNb1        $ unset $A

u T!Dwa^C P1K1

事實上所取消的變量是B而不是A
T.Y ^5Z _M-v3m1
MB0vjx*B2K�D5Y a1
此外,變量一旦經過unset取消之後,其結果是將整個變量拿掉,而不僅是取消其變量值。BSD愛好者樂園+z H/7b1HE
如下兩行其實是很不一樣的:BSD愛好者樂園 ptJhd8y0j7G

        $ A=
8d"eC/m9e+Y ]1        $ unset A

o?HUG,]1

第一行只是將變量A設定爲"空值"(null  value),但第二行則讓變量A不在存在。
S"r[#xTD1
雖然用眼睛來看,這兩種變量狀態在如下命令結果中都是一樣的:BSD愛好者樂園2yL&Mw�vT }-WW

        $ A=BSD愛好者樂園+MG*F Us)j5k
        $ echo $ABSD愛好者樂園i%y~#io$A n-ci-I
BSD愛好者樂園K*pS%[J
        $ unset ABSD愛好者樂園m2/nV ^
        $ echo $A
BSD愛好者樂園K.M4V@q"P�{P[

7O9z / o,OmuT[1[版權聲

發佈了42 篇原創文章 · 獲贊 5 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章