shell十三問之5:問var=value 在export前後的差在哪?
這次讓我們暫時丟開command line
,
先了解一下bash變量(variable)吧...
所謂的變量,就是利用一個固定的"名稱"(name), 來存取一段可以變化的"值"(value)。
1. 變量設定(set)
在bash中, 你可以用"="來設定或者重新定義變量的內容:
name=value
在設定變量的時候,得遵守如下規則:
- 等號左右兩邊不能使用分隔符號(IFS),也應避免使用shell的保留元字符(meta charactor);
- 變量的名稱(name)不能使用$符號;
- 變量的名稱(name)的首字符不能是數字(number)。
- 變量的名稱(name)的長度不可超過256個字符。
- 變量的名稱(name)及變量的值的大小寫是有區別的、敏感的(case sensitive,)
如下是一些變量設定時常見的錯誤:
A= B #=號前後不能有IFS
1A=B #變量名稱不能以數字開頭
$A=B #變量的名稱裡有$
a=B #這跟a=b是不同的,(這不是錯誤,提醒windows用戶)
如下則是可以接受的設定:
A=" B" #IFS被關閉,參考前面的quoting章節
A1=B #並非以數字開頭
A=$B #$可用在變量的值內
This_Is_A_Long_Name=b #可用_連接較長的名稱或值,且有大小區別;
2. 變量替換(substitution)
shell 之所以強大,其中的一個因素是它可以在命令行中對變量作 替換(substitution)處理。 在命令行中使用者可以使用$符號加上變量名稱(除了用=定義變量名稱之外), 將變量值給替換出來,然後再重新組建命令行。
比方:
$ A=ls
$ B=la
$ C=/tmp
$ $A -$B $C
以上命令行的第一個$
是shell prompt
, 並不在命令行之內。
必須強調的是,我們所提的變量替換,只發生在command line
上面。
(是的,請讓我們再次回到命令行吧!) 仔細分析,最後那行
command line
,不難發現在被執行前(在輸入CR
字符之前),
$
符號對每一個變量作替換處理(將變量的值替換出來再重組命令行),
最後會得出如下命令行:
ls -la /tmp
還記得第二章,我請大家"務必理解"的那兩句嗎? 若你忘了,我這裡重貼一遍:
Note:
若從技術的細節來看,
shell
會依據IFS
(Internal Field Seperator) 將command line
所輸入的文字拆解為"字段"(word/field)。 然後再針對特殊字符(meta)先作處理,最後重組整行command line
。
這裡的$
就是command line
中最經典的meta之一了,
就是作變量替換的。在日常的shell操作中,
我們常會使用echo
命令來查看特定的變量的值,
例如:
$ echo $A -$B $C
我們已學過,echo
命令只單純將其argument送至"標準輸出"(stdout, 通常是我們的屏幕)。
所以上面的命令會在屏幕上得到如下結果:
ls -al /tmp
這是由於echo
命令在執行時,會先將$A
(ls)、$B
(la)跟$C
(/tmp)給替換出來;
利用shell對變量的替換處理能力,我們在設定變量時就更為靈活了:
A=B
B=$A
這樣,B的變量值就可繼承A變量"當時"的變量值了。 不過,不要以"數學邏輯"來套用變量的設定,比方說:
A=B
B=C
這樣,並不會讓A的變量值變成C。再如:
A=B
B=$A
A=C
同樣也不會讓B的值變成C。
上面是單純定義了兩個不同名稱的變量: A 與 B, 它們的取值分別是C與B。
若變量被重複定義的話,則原有值為新值所取代。(這不正是"可變的量"嗎?^_^) 當我們在設定變量的時候,請記住這點:用一個名稱存儲一個數值, 僅此而已。
此外, 我們也可以利用命令行的變量替換能力來"擴充"(append)變量的值:
A=B:C:D
A=$A:E
這樣, 第一行我們設定A的值為"B:C:D", 然後,第二行再將值擴充為"B:C:D:E"。
上面的擴充的範例,我們使用分隔符號(:)來達到擴充的目的, 要是沒有分隔符的話,如下是有問題的:
A=BCD
B=$AE
因為第二次是將A的值繼承$AE的替換結果,而非$A再加E。 要解決此問題,我們可用更嚴謹的替換處理:
A=BCD
A=${A}E
上例中,我們使用{}將變量名稱範圍給明確定義出來, 如此一來, 我們就可以將A的變量值從BCD給擴充為BCDE。
Tips: 關於${name}事實上還可以做到更多的變量處理能力, 這些均屬於比較進階階段的變量處理,現階段暫不介紹了, 請大家自行參考資料。
3. export 變量
嚴格來說,我們在當前shell中所定義的變量,均屬於
"本地變量"(local variable), 只有經過export
命令的
"輸出"處理,才能成為"環境變量"(environment variable):
$ A=B
$ export A
或者
$ export A=B
經過export
輸出處理之後,變量A就能成為一個環境變量
供其後的命令使用。在使用export
的時候,請別忘記
shell在命令行對變量的"替換"(substitution)處理。
比方說:
$ A=B
$ B=C
$ export $A
上面的命令並未將A輸出為"環境變量",而是將B導出
這是因為在這個命令行中,$A會首先被替換為B,然後在"塞回"
作export
的參數。
要理解這個export
,事實上需要從process(進程)的角度來理解才能透徹。
我們將於下一章為大家說明process(進程)的概念,敬請留意。
4. 取消變量(unset)
要取消一個變量,在bash中可使用unset
命令來處理:
unset A
與export
一樣,unset
命令行,也同樣會作
變量替換(這其實是shell的功能之一),
因此:
$ A=B
$ B=C
$ unset $A
事實上,所取消的是變量B而不是A。
此外,變量一旦經過unset取消之後, 其結果是將整個變量拿掉,而不是取消變量的值。
如下兩行其實是很不一樣的:
$ A=
$ unset A
第一行只是將變量A設定為"空值"(null value), 但第二行則是讓變量A不存在。 雖然用眼睛來看, 這兩種變量的狀態在如下的命令結果中都是一樣的:
$ A=
$ echo $A
$ unset A
$ echo $A
請學員務必能識別null value 與 unset的本質區別, 這在一些進階的變量處理上是很嚴格的。
比方說:
$ str= #設為null
$ var=${str=expr} #定義var
$ echo $var
$ echo $str
$ unset str #取消str
$ var=${str=expr} #定義var
$ echo $var
expr
$ echo $str
expr
聰明的讀者(yes, you!),稍加思考的話, 應該不難發現為何同樣的var=${str=expr} 在str為null與unset之下的不同吧? 若你看不出來,那可能是如下原因之一:
- 你太笨了
- 不瞭解 var=${str=expr} 這個進階處理
- 對本篇說明還沒有來得及消化吸收
- 我講得不好
不知,您選哪個呢?...... ^_^.