嚴格來說,shell中沒有表示式的概念。Shell本身事實上僅僅是一堆命令的集合。當然也不是胡亂的堆在一起。而是有一定的組織。僅僅是這個組織不那麼嚴謹。所以本文不是要真的總結所謂的表示式,而是把shell中一些犄角旮旯的東西拼湊在一起。實在不知道它們屬於那個分類。
。
- 命令代換
事實上就是這篇文章中的反引號所起的作用。可是命令代換還有還有一種形式,例如以下:
m@meng:~/scripts$ m=`date`
m@meng:~/scripts$ echo $m
2015年 06月 25日 星期四 10:40:24 CST
m@meng:~/scripts$ n=$(date)
m@meng:~/scripts$ echo $n
2015年 06月 25日 星期四 10:40:37 CST
也就是說,`command`和$(command)的效果是一樣的。
- 算術代換
前面說過,將一個變數宣告為整數型別時。它就能夠做算術運算,或者說,賦值給這個變數的數字不再被當成字串。而是真正的數字。假設沒有這個整數宣告。那麼把一個數字或算術表示式賦值給一個變數時,它的值仍被視為普通字串。
可是如今,有還有一個方法能夠達到這個效果,就是符號$((expr))。處於內括號裡的變數將直接被視為整數。而不必事先宣告其為整數型別。例如以下:
m@meng:~/scripts$ r=3+4
m@meng:~/scripts$ echo $r
3+4
m@meng:~/scripts$ echo $(($r))
7
m@meng:~/scripts$ echo $(($r+3))
10
只是,$(()) 中僅僅能用+-*/和()運算子,而且僅僅能做整數運算。
- 引號
Shell指令碼中的單引號和雙引號一樣都是字串的界定符,兩者的差別在於,單引號中的全部字元都被視為普通字元。而捨棄其功能含義。比方’$’是變數值提取符,可是放在單引號中就是’\$’的字面值,例如以下:
m@meng:~/scripts$ q=5
m@meng:~/scripts$ echo "$q"
5
m@meng:~/scripts$ echo '$q'
$q
所以,在單引號中使用變數一定要小心。
所謂界定符。事實上就是將界定符內的字串視為一個總體,而不會被空格等分隔符打斷。
在雙引號內,全部的特殊字元將保持其轉義含義,如上面的’$’。假設想讓雙引號中的某個特殊字元恢復其本來面目。即取其字面值,能夠在它前面加入轉義字元’\’。例如以下:
m@meng:~/scripts$ echo "\$q"
$q
- 退出狀態
在shell中,能夠覺得一條命令就是一個表示式。表示式都是有值的。而一條命令的值是什麼呢?是它的執行結果嗎?比方ls列出來的檔案?實際上。能夠把命令的出口狀態視為“命令表示式”的值:命令執行完畢後,會有一個出口狀態來表示這條命令是否執行成功,普通情況下,shell中命令執行成功出口狀態為0;失敗為1或其它非0值。能夠使用系統變數“#?”來查詢上一條命令的出口狀態。如:
m@meng:~/scripts$ grep m new
m@meng:~/scripts$ echo $?
1
m@meng:~/scripts$ cat new
的
m@meng:~/scripts$ echo $?
0
m@meng:~/scripts$ m=4
m@meng:~/scripts$ echo $?
0
上例,grep命令在new檔案裡沒有找到字元”m”,所以其出口狀態為1;其它都為0,包含賦值語句。
退出狀態經經常使用做if語句的推斷條件。
test表示式
儘管能夠直接使用命令的出口狀態作為if、while等語句的推斷條件,可是更常使用的卻是test等專門的測試命令。
test命令的語法為:
test 表示式
test主要用來執行三類測試:檔案屬性、數值比較、字串比較。假設測試結果為真,則該命令的Exit Status為0,假設測試結果為假,則命令的Exit Status為1。檔案測試
格式為: test options file。基本的options包含:- -e 測試file的存在性,若存在則值為0;否則為1。這個結果跟執行普通命令得到的出口狀態是一致的。
- -d 測試file是否為資料夾,是為0。否為1。
- -f 若file是普通檔案,結果為真(即,值為0).
- -s 測試檔案是否為非空,若file存在且非空,為0;否則,即不存在或者是空檔案,為1。
- -r file存在且僅僅讀,為真。
- -w file存在且可寫,為真。
- -x file存在且可執行,為真。
數字測試
數字測試的比較運算子居然使用的是文字。對照方下(左側是C語言使用的傳統的運算子。右側是shell使用的):
== : -eq
!= : -ne
> : -gt
\< : -lt
>= : -ge
\<= : -le字串測試
-z str: 若str的長度是0。結果為真(謹記:真 <==> $? == 0)
-n str: 若str的長度不是0,結果為真
s1 = s2 : 兩個字串相等,結果為真
s1 != s2 : 兩個字串不等。結果為真
str : 不加不論什麼選項來測試str。效果同-n
[ ] 表示式
實際上。僅僅有 [ 是命令。而 ] 僅僅是界定符。[ 命令與test命令基本同樣,唯一的差別就是格式不同,[ 命令須要將要測試的表示式置於括號裡,###且表示式左右兩邊分別要和[ ]留一個空格###。如[ -z “empty” ]。據說,[ 命令的效率略微高一些,我沒驗證過。
還有一點:###[ 命令不支援運算子“>”和“<”###。所以對於字串比較運算的支援可能差一點,這是唯二的差別。。。。[[ ]]表示式
擴充套件了[ ]命令。首先就是支援了運算子“>”和“<”,另外還支援邏輯運算&&,||。!,例如以下:
m@meng:~/scripts$ [ er > et ]
m@meng:~/scripts$ echo $?
0
m@meng:~/scripts$ [[ er > et ]]
m@meng:~/scripts$ echo $?
1
顯然,er > et結果應該為假,所以測試表示式的出口狀態是1。
可是[]沒有效果,而[[ ]]測試正確。
m@meng:~/scripts$ [ er > et || er < et ]
bash: [: 缺少 `]`
er:未找到命令
m@meng:~/scripts$ [[ er > et || er < et ]]
m@meng:~/scripts$ echo $?
0
m@meng:~/scripts$ [[ er > et && er < et ]]
m@meng:~/scripts$ echo $?
1
- 算術表示式
- (( ))表示式
似乎有點凌亂了,(( ))與$(( ))的差別在於。後者能夠把計算結果提取出來作為一個值使用,我個人感覺,’$’這個符號就是用來提取值的,比方引用變數的時候也用它。而符號(( ))僅僅是完畢計算本身,至於儲存結果。儘管也能夠,可是不是主業。還是直接看命令吧:
- (( ))表示式
m@meng:~/scripts$ ((m=4-2))
m@meng:~/scripts$ echo $m
2
m@meng:~/scripts$ m=$((4-2))
m@meng:~/scripts$ echo $m
2
這意味著,((m=4-2))和m=$((4-2))效果是一樣的。也就是說在(())內部能夠直接完畢賦值。
~~~~
m@meng:~/scripts$ echo $((4-2))
2
m@meng:~/scripts$ echo ((4-2))
bash: 未預期的符號 '(' 附近有語法錯誤
這說明。(())不負責儲存結果,想要結果的話,用’$’來提取。
~~~~
m@meng:~/scripts$ m=3;n=2
m@meng:~/scripts$ echo $((m-n))
1
這說明,在(())內部使用變數時,不須要加入’$’符號。
~~~~
m@meng:~/scripts$ m=3;n=2
m@meng:~/scripts$ echo $((m<n))
0
m@meng:~/scripts$ echo $((m>n))
1
顯然,(())還支援比較運算,唯一的問題是。它的出口狀態與test等其它命令恰好相反!
~~~~
總結一下這個表示式:
1、僅僅支援整數運算。
2、支援的運算包含:=(賦值)、==(相等)、>= <= < > % + - * / -= += /= *= %=。非常豐富了。
- let表示式
與上面那個基本一樣。僅僅是格式不同罷了。let中表示式寫在let後面。而不是括號裡。另外,因為不像(())有天然的界定符。所以算式中有空格時,須要用引號括起來。 - expr表示式
以後再寫吧。好累。。。上面的已經夠用了。
邏輯運算
主要有&&、||、-a、-o、!和(),用來計算表示式之間的邏輯運算。支援用括號()來進行組合,邏輯運算子和表示式之間要有空格。
[[]]命令僅僅支援符號,不支援-a和-o選項。
m@meng:~/scripts$ [[ er > et -o er < et ]]
bash: 條件表示式中有語法錯誤
bash: '-o' 附近有語法錯誤
完。