1 shell變量基礎
shell變量是一種很「弱」的變量,默認狀況下,一個變量保存一個串,shell不關心這個串是什麼含義。因此若要進行數學運算,必須使用一些命令例如let、declare、expr、雙括號等。shell變量可分爲兩類:局部變量和環境變量。局部變量只在建立它們的shell中可用。而環境變量則能夠在建立它們的shell及其派生出來的任意子進程中使用。有些變量是用戶建立的,其餘的則是專用shell變量。變量名必須以字母或下劃線字符開頭。其他的字符能夠是字母、數字(0~9)或下劃線字符。任何其餘的字符都標誌着變量名的終止。名字是大小寫敏感的。給變量賦值時,等號周圍不能有任何空白符。爲了給變量賦空值,能夠在等號後跟一個換行符。用set命令能夠查看全部的變量,unset var命令能夠清除變量var,var至關於沒有定義過。readonly var能夠把var變爲只讀變量,定義以後不能對var進行任何更改。對shell變量的引用方式不少,用這些方式能夠方便的獲取shell變量的值,變量值的長度,變量的一個字串,變量被部分替換後的值等等。shell變量常見引用方式以下:html
2 環境變量
環境變量的定義方法以下:
var=value
export var
shell在初始化的時候會在執行profile等初始化腳本,腳本中定義了一些環境變量,這些變量會在建立子進程時傳遞給子進程。
用env命令能夠查看當前的環境變量。經常使用的系統環境變量以下:
_(下劃線) 上一條命令的最後一個參數
BASH 展開爲調用bash實例時使用的全路徑名
CDPATH cd命令的搜索路徑。它是以冒號分隔的目錄列表,shell經過它來搜索cd命令指定的目標目錄。例如.:~:/usr
EDITOR 內置編輯器emacs、gmacs或vi的路徑名
ENV 每個新的bash shell(包括腳本)啓動時執行的環境文件。一般賦予這個變量的文件名是.bashrc。
EUID 展開爲在shell啓動時被初始化的當前用戶的有效ID
GROUPS 當前用戶所屬的組
HISTFILE 指定保存命令行歷史的文件。默認值是~/.bash_history。若是被複位,交互式shell退出時將不保存命令行歷史
HISTSIZE 記錄在命令行歷史文件中的命令數。默認是500
HOME 主目錄。未指定目錄時,cd命令將轉向該目錄
IFS 內部字段分隔符,通常是空格符、製表符和換行符,用於由命令替換,循環結構中的表和讀取的輸入產生的詞的字段劃分
LANG 用來爲沒有以LC_開頭的變量明確選取的種類肯定locale類
OLDPWD 前一個工做目錄
PATH 命令搜索路徑。一個由冒號分隔的目錄列表,shell用它來搜索命令,一個普通值爲 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
PPID 父進程的進程ID
PS1 主提示符串,默認值是$
PS2 次提示符串,默認值是>
PS3 與select命令一塊兒使用的選擇提示符串,默認值是#?
PS4 當開啓追蹤時使用的調試提示符串,默認值是+。追蹤能夠用set –x開啓
PWD 當前工做目錄。由cd設置
RANDOM 每次引用該變量,就產生一個隨機整數。隨機數序列能夠經過給RANDOM賦值來初始化。若是RANDOM被複位,即便隨後再設置,它也將失去特定的屬性
REPLY 當沒有給read提供參數時設置
SHELL 當調用shell時,它掃描環境變量以尋找該名字。shell給PATH、PS一、PS二、MAILCHECK和IFS設置默認值。HOME和MAIL由login(1)設置
SHELLOPTS 包含一列開啓的shell選項,好比braceexpand、hashall、monitor等
UID 展開爲當前用戶的用戶ID,在shell啓動時初始化
3 數值變量
shell中默認把變量值看成字符串,例如:
age=22
age=${age}+1
echo ${age}
輸出結果爲22+1,而不是23,由於shell將其解釋爲字符串,而不是數學運算。
能夠用let命令使其進行數學運算,例如:
let age=${age}+1
也能夠用declare把變量定義爲整型。例如:
declare -i age=22
這裏就用 -i 選項把age定義爲整型的了。此後每次運算,都把age的右值識別爲算術表達式或數字。
4 數組
在shell中可使用數組,例如:
array[0]=0
array[1]=1
array[2]=2
則array就是一個數組,也能夠這樣給數組初始化:
array=(0 1 2) // 元素之間以空格分隔
能夠經過 ${array[$i]}來訪問array中某個元素,${array[*]} 的返回值即數組的全部元素組成的串,${#array[*]} 的返回值即數組的元素個數,${array[*]:0:2} 返回第一個和第二個元素組成的串。0表示開始的位置,2表示要返回的元素個數,開始位置能夠爲0-2(0減去2)之類的,表示從倒數第二個元素開始。
下面寫個稍微複雜點的例子:shell
1 #!/bin/bash 2 for ((i=0; i<100; i++)) 3 do 4 array[$i]=$i 5 done 6 for ((i=0; i<100; i++)) 7 do 8 echo ${array[$i]} 9 done
若是要使用二維數組甚至三維數組該怎麼實現呢,那就須要用eval命令來模擬數組的功能了。
eval命令的做用是掃描命令兩次再執行,若是不使用eval,只掃描一次,而後執行。看個例子:
root@suse:~$ name=Barry
root@suse:~$ $name=hello
Barry=hello: command not found
爲何第二句給Barry變量賦值會出錯呢?從報錯信息能夠發現shell並無識別這是個賦值語句,而是把Barry=hello看成一個命令來執行,固然會報錯。爲何不能識別這是賦值語句呢?第一次掃描時,由於掃描到$符號,因此不能把這句看成賦值語句,賦值語句的左邊老是一個變量名,而不該該是$開頭的。因此第一次掃描僅僅識別了$name變量,並作了替換,而並無認識到賦值語句。
若是使用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以後,對 $name=hello 第一次掃描替換了$name,沒有識別賦值語句,第二次掃描識別是賦值語句,而後執行。如今大約能夠想到怎樣用eval實現二維數組了。
下面實現的二維數組每一行表明一我的的信息記錄,包括姓名,年齡。數組
1 for ((i=0; i<2; i++)) 2 do 3 for ((j=0; j<2; j++)) 4 do 5 read man$i$j 6 done 7 done 8 echo "next print:" 9 for ((i=0; i<2; i++)) 10 do 11 for ((j=0; j<2; j++)) 12 do 13 eval echo -n "\$man$i$j:" 14 done 15 printf "\n" 16 done
5 特殊變量
$0:當前腳本的文件名
$num:num爲從1開始的數字,$1是第一個參數,$2是第二個參數,${10}是第十個參數
$#:傳入腳本的參數的個數
$*:全部的位置參數(做爲單個字符串)
$@:全部的位置參數(每一個都做爲獨立的字符串)。
$?:當前shell進程中,上一個命令的返回值,若是上一個命令成功執行則$?的值爲0,不然爲其餘非零值,經常使用作if語句條件
$$:當前shell進程的pid
$!:後臺運行的最後一個進程的pid
$-:顯示shell使用的當前選項
$_:以前命令的最後一個參數bash