Shell特殊變量和命令行參數(shù)詳解
1.shell變量基礎(chǔ)
shell變量是一種很“弱”的變量,默認(rèn)情況下,一個(gè)變量保存一個(gè)串,shell不關(guān)心這個(gè)串是什么含義。
所以若要進(jìn)行數(shù)學(xué)運(yùn)算,必須使用一些命令例如let、declare、expr、雙括號(hào)等。
shell變量可分為兩類:局部變量和環(huán)境變量。
局部變量只在創(chuàng)建它們的shell中可用;而環(huán)境變量則可以在創(chuàng)建它們的shell及其派生出來的任意子進(jìn)程中使用。
有些變量是用戶創(chuàng)建的,其他的則是專用shell變量。
變量名必須以字母或下劃線字符開頭。其余的字符可以是字母、數(shù)字(0~9)或下劃線字符。
任何其他的字符都標(biāo)志著變量名的終止。
名字是大小寫敏感的。
給變量賦值時(shí),等號(hào)周圍不能有任何空白符。
為了給變量賦空值,可以在等號(hào)后跟一個(gè)換行符。
用set命令可以查看所有的變量,unset var命令可以清除變量var,var相當(dāng)于沒有定義過。readonly var可以把var變?yōu)橹蛔x變量,定義之后不能對(duì)var進(jìn)行任何更改。
對(duì)shell變量的引用方式很多,用這些方式可以方便的獲取shell變量的值,變量值的長(zhǎng)度,變量的一個(gè)字串,變量被部分替換后的值等等。
shell變量常見引用方式如下:
2.環(huán)境變量
環(huán)境變量的定義方法如下:
var=value
export var
shell在初始化的時(shí)候會(huì)在執(zhí)行profile等初始化腳本,腳本中定義了一些環(huán)境變量,這些變量會(huì)在創(chuàng)建子進(jìn)程時(shí)傳遞給子進(jìn)程。
用env命令可以查看當(dāng)前的環(huán)境變量。常用的系統(tǒng)環(huán)境變量如下:
_(下劃線):上一條命令的最后一個(gè)參數(shù)
BASH:展開為調(diào)用bash實(shí)例時(shí)使用的全路徑名
CDPATH:cd命令的搜索路徑。它是以冒號(hào)分隔的目錄列表,shell通過它來搜索cd命令指定的目標(biāo)目錄。例如.:~:/usr
EDITOR:內(nèi)置編輯器emacs、gmacs或vi的路徑名
ENV:每一個(gè)新的bash shell(包括腳本)啟動(dòng)時(shí)執(zhí)行的環(huán)境文件。通常賦予這個(gè)變量的文件名是.bashrc。
EUID:展開為在shell啟動(dòng)時(shí)被初始化的當(dāng)前用戶的有效ID
GROUPS:當(dāng)前用戶所屬的組
HISTFILE:指定保存命令行歷史的文件。默認(rèn)值是~/.bash_history。如果被復(fù)位,交互式shell退出時(shí)將不保存命令行歷史
HISTSIZE:記錄在命令行歷史文件中的命令數(shù)。默認(rèn)是500
HOME:主目錄。未指定目錄時(shí),cd命令將轉(zhuǎn)向該目錄
IFS:內(nèi)部字段分隔符,一般是空格符、制表符和換行符,用于由命令替換,循環(huán)結(jié)構(gòu)中的表和讀取的輸入產(chǎn)生的詞的字段劃分
LANG:用來為沒有以LC_開頭的變量明確選取的種類確定locale類
OLDPWD:前一個(gè)工作目錄
PATH:命令搜索路徑。一個(gè)由冒號(hào)分隔的目錄列表,shell用它來搜索命令,一個(gè)普通值為 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
PPID:父進(jìn)程的進(jìn)程ID
PS1:主提示符串,默認(rèn)值是$
PS2:次提示符串,默認(rèn)值是>
PS3:與select命令一起使用的選擇提示符串,默認(rèn)值是#?
PS4:當(dāng)開啟追蹤時(shí)使用的調(diào)試提示符串,默認(rèn)值是+。追蹤可以用set –x開啟
PWD:當(dāng)前工作目錄。由cd設(shè)置
RANDOM:每次引用該變量,就產(chǎn)生一個(gè)隨機(jī)整數(shù)。隨機(jī)數(shù)序列可以通過給RANDOM賦值來初始化。如果RANDOM被復(fù)位,即使隨后再設(shè)置,它也將失去特定的屬性
REPLY:當(dāng)沒有給read提供參數(shù)時(shí)設(shè)置
SHELL:當(dāng)調(diào)用shell時(shí),它掃描環(huán)境變量以尋找該名字。shell給PATH、PS1、PS2、MAILCHECK和IFS設(shè)置默認(rèn)值。HOME和MAIL由login(1)設(shè)置
SHELLOPTS:包含一列開啟的shell選項(xiàng),比如braceexpand、hashall、monitor等
UID:展開為當(dāng)前用戶的用戶ID,在shell啟動(dòng)時(shí)初始化
3.數(shù)值變量
shell中默認(rèn)把變量值當(dāng)作字符串,例如:
- age=22
- age=${age}+1
- echo ${age}
輸出結(jié)果為22+1,而不是23,因?yàn)閟hell將其解釋為字符串,而不是數(shù)學(xué)運(yùn)算。
可以用let命令使其進(jìn)行數(shù)學(xué)運(yùn)算,例如:
- let age=${age}+1
也可以用declare把變量定義為整型。例如:
- declare -i age=22
這里就用 -i 選項(xiàng)把a(bǔ)ge定義為整型的了。此后每次運(yùn)算,都把a(bǔ)ge的右值識(shí)別為算術(shù)表達(dá)式或數(shù)字。
4.數(shù)組
在shell中可以使用數(shù)組,例如:
- array[0]=0
- array[1]=1
- array[2]=2
則array就是一個(gè)數(shù)組,也可以這樣給數(shù)組初始化:
- array=(0 1 2) // 元素之間以空格分隔
可以通過 ${array[$i]}來訪問array中某個(gè)元素,${array[*]} 的返回值即數(shù)組的所有元素組成的串,${#array[*]} 的返回值即數(shù)組的元素個(gè)數(shù),${array[*]:0:2} 返回第一個(gè)和第二個(gè)元素組成的串。
0表示開始的位置,2表示要返回的元素個(gè)數(shù),開始位置可以為0-2(0減去2)之類的,表示從倒數(shù)第二個(gè)元素開始。
下面寫個(gè)稍微復(fù)雜點(diǎn)的例子:
如果要使用二維數(shù)組甚至三維數(shù)組該怎么實(shí)現(xiàn)呢,那就需要用eval命令來模擬數(shù)組的功能了。
eval命令的作用是掃描命令兩次再執(zhí)行,如果不使用eval,只掃描一次,然后執(zhí)行??磦€(gè)例子:
- root@suse:~$ name=Barry
- root@suse:~$ $name=hello
- Barry=hello: command not found
為什么第二句給Barry變量賦值會(huì)出錯(cuò)呢?
從報(bào)錯(cuò)信息可以發(fā)現(xiàn)shell并沒有識(shí)別這是個(gè)賦值語(yǔ)句,而是把Barry=hello當(dāng)作一個(gè)命令來執(zhí)行,當(dāng)然會(huì)報(bào)錯(cuò)。
為什么不能識(shí)別這是賦值語(yǔ)句呢?
第一次掃描時(shí),因?yàn)閽呙璧?符號(hào),所以不能把這句當(dāng)作賦值語(yǔ)句,賦值語(yǔ)句的左邊總是一個(gè)變量名,而不應(yīng)該是$開頭的。
所以第一次掃描僅僅識(shí)別了$name變量,并做了替換,而并沒有認(rèn)識(shí)到賦值語(yǔ)句。
如果使用eval $name=hello呢?
- root@suse:~$ name=Barry
- root@suse:~$ $name=hello
- Barry=hello: command not found
- root@suse:~$ eval $name=hello
- root@suse:~$ echo $Barry
- hello
可見使用了eval之后,對(duì) $name=hello 第一次掃描替換了$name,沒有識(shí)別賦值語(yǔ)句,第二次掃描識(shí)別是賦值語(yǔ)句,然后執(zhí)行。
現(xiàn)在大約可以想到怎樣用eval實(shí)現(xiàn)二維數(shù)組了。
下面實(shí)現(xiàn)的二維數(shù)組每一行代表一個(gè)人的信息記錄,包括姓名,年齡。
5.特殊變量
$0:當(dāng)前腳本的文件名
$num:num為從1開始的數(shù)字,$1是第一個(gè)參數(shù),$2是第二個(gè)參數(shù),${10}是第十個(gè)參數(shù)
$#:傳入腳本的參數(shù)的個(gè)數(shù)
$*:所有的位置參數(shù)(作為單個(gè)字符串)
$@:所有的位置參數(shù)(每個(gè)都作為獨(dú)立的字符串)。
$?:當(dāng)前shell進(jìn)程中,上一個(gè)命令的返回值,如果上一個(gè)命令成功執(zhí)行則$?的值為0,否則為其他非零值,常用做if語(yǔ)句條件
$$:當(dāng)前shell進(jìn)程的pid
$!:后臺(tái)運(yùn)行的最后一個(gè)進(jìn)程的pid
$-:顯示shell使用的當(dāng)前選項(xiàng)
$_:之前命令的最后一個(gè)參數(shù)