SHELL腳本--expr命令全解

bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.htmlhtml


expr命令能夠實現數值運算、數值或字符串比較、字符串匹配、字符串提取、字符串長度計算等功能。它還具備幾個特殊功能,判斷變量或參數是否爲整數、是否爲空、是否爲0等。正則表達式

1.expr中文手冊(info expr)

先看expr命令的info文檔 info expr 的翻譯。shell

16.4.1 字符串表達式
-------------------------
'expr'支持模式匹配和字符串操做。字符串表達式的優先級高於數值表達式和邏輯關係表達式。
 
'STRING : REGEX'
     執行模式匹配。兩端參數會轉換爲字符格式,且第二個參數被視爲正則表達式(GNU基本正則),它默認會隱含前綴"^"。隨後將第一個參數和正則模式作匹配。
 
     若是匹配成功,且REGEX使用了'\(''\)',則此表達式返回匹配到的,若是未使用'\('和'\)',則返回匹配的字符數。
 
     若是匹配失敗,若是REGEX中使用了'\(''\)',則此表達式返回空字符串,不然返回爲0。
 
     只有第一個'\(...\)'會引用返回的值;其他的'\(...\)'只在正則表達式分組時有意義。
 
     在正則表達式中,'\+''\?''\|'分表表明匹配一個或多個,0個或1個以及兩端任選其一的意思。
 
'match STRING REGEX'
     等價於'STRING : REGEX''substr STRING POSITION LENGTH'
     返回STRING字符串中從POSITION開始,長度最大爲LENGTH的子串。若是POSITION或LENGTH爲負數,0或非數值,則返回空字符串。
 
'index STRING CHARSET'
     CHARSET中任意單個字符在STRING中最前面的字符位置。若是在STRING中徹底不存在CHARSET中的字符,則返回0。見後文示例。
    
'length STRING'
     返回STRING的字符長度。
 
'+ TOKEN'
     將TOKEN解析爲普通字符串,即便TOKEN是像MATCH或操做符"/"同樣的關鍵字。這使得'expr length + "$x"''expr + "$x" : '.*/\(.\)''能夠正常被測試,即便"$x"的值多是'/''index'關鍵字。這個操做符是一個GUN擴展。
     通用可移植版的應該使用'" $token" : ' \(.*\)''來代替'+ "$token"'。
 
   要讓expr將關鍵字解析爲普通的字符,必須使用引號包圍。
 
16.4.2 算術表達式
--------------------------
 
'expr'支持普通的算術操做,算術表達式優先級低於字符串表達式,高於邏輯關係表達式。
 
'+ -'
     加減運算。兩端參數會轉換爲整數,若是轉換失敗則報錯。
 
'* / %'
     乘,除,取模運算。兩端參數會轉換爲整數,若是轉換失敗則報錯。
 
16.4.3 邏輯關係表達式
---------------------------
 
'expr'支持普通的邏輯鏈接和邏輯關係。它的優先級最低。
 
'|'
     若是第一個參數非空且非0,則返回第一個參數的值,不然返回第二個參數的值,但要求第二個參數的值也是非空或非0,不然返回0。若是第一個參數是非空或非0時,不會計算第二個參數。
    
     通過測試,以上手冊內容是錯誤的。正確的應該是:若是第一個參數非0,則返回第一個參數的值,不然返回第二個參數。但若是任意一個參數爲空,則報錯。除非空字符串使用引號包圍,此時將和0的處理方式同樣。
 
'&'
     若是兩個參數都非空且非0,則返回第一個參數,不然返回0。若是第一個參爲0或爲空,則不會計算第二個參數。
    
     通過測試,以上手冊內容是錯誤的。正確的應該是:若是兩個參數都非0,則返回第一個參數,不然返回0。但任意一個參數爲空,則報錯。除非空字符串使用引號包圍,此時將和0的處理方式同樣。
 
'< <= = == != >= >'
     比較兩端的參數,若是爲true,則返回1,不然返回0。"==""="的同義詞。"expr"首先嚐試將兩端參數轉換爲整數,並作算術比較,若是轉換失敗,則按字符集排序規則作字符比較。
 
括號'()'能夠改變優先級,但使用時須要使用反斜線對括號進行轉義。
 
16.4.4 'expr'使用示例
-------------------------------
 
如下爲expr的一些示例,其中有將shell的元字符使用引號包圍的示例。
 
   將shell中變量'foo'的值增長1:
 
     foo=$(expr $foo + 1)
 
   輸出變量路徑變量'$fname'中不包含'/'的文件名部分:
 
     expr $fname : '.*/\(.*\)' '|' $fname
    
     解釋:其中的'|'是expr中的鏈接符,只不過是被引號包圍防止被shell解析。例如$fname=/etc/hosts,則此表達式返回hosts,若是$fname=/usr/share/,則此表達式'|'的左邊爲空,因此返回'|'右邊的值,即$fname,即返回/usr/share/。
 
   An example showing that '\+' is an operator:
 
     expr aaa : 'a\+'    # 解釋:由於REGEX部分沒有使用\(\),因此返回匹配的字符數
     => 3
 
     expr abc : 'a\(.\)c'  # 解釋:由於REGEX部分使用了\(\),因此返回匹配的字符
     => b
     expr index abcdef cz
     => 3
     expr index index a    # 解釋:由於第二個index是關鍵字
     error-> expr: syntax error
     expr index + index a  # 解釋:使用+將index關鍵字解析爲普通字符串
     => 0

2.expr使用示例

下面將使用示例來介紹expr的用法,在介紹以前,須要注意三點:bash

(1).數值表達式("+ - * / %")和比較表達式("< <= = == != >= >")會先將兩端的參數轉換爲數值,轉換失敗將報錯。因此可藉此來判斷參數或變量是否爲整數。測試

(2).expr中的不少符號須要轉義或使用引號包圍。spa

(3).全部操做符的兩邊,都須要有空格。翻譯

如下是expr示例。code

(1)."string : REGEX"字符串匹配示例。要輸出匹配到的字符串結果,須要使用"\("和"\)",不然返回的將是匹配到的字符串數量。htm

[root@xuexi ~]# expr abcde : 'ab\(.*\)'
cde

[root@xuexi ~]# expr abcde : 'ab\(.\)'
c

[root@xuexi ~]# expr abcde : 'ab.*'  
5

[root@xuexi ~]# expr abcde : 'ab.'   
3

[root@xuexi ~]# expr abcde : '.*cd*'
4

注意,因爲REGEX中隱含了"^",因此使得匹配時都是從string首字符開始的。blog

[root@xuexi ~]# expr abcde : 'cd.*'  
0

之因此爲0,是由於真正的正則表達式是"^cd.*",而abcde不是c開頭而是a開頭的,因此沒法匹配到任何結果。所以,任何字符串匹配時,都應該從首字符開始。

字符串匹配時,會先將兩端參數轉換爲字符格式。

(2)."index string chars"用法示例。

該表達式是從string中搜索chars中某個字符的位置,這個字符是string中最靠前的字符。例如:

[root@xuexi ~]# expr index abcde dec
3

該命令將對字符串"dec"逐字符分解,首先分解獲得第一個字符d,從abcde中搜索到d的位置爲4,再分解獲得第二個字符e,該字符在abcde中的位置爲5,最後獲得的字符是c,該字符在abcde中的位置爲3。其中3是最靠前的字符,因此命令返回的結果爲3。

[root@xuexi ~]# expr index abcde xdc
3

若是chars中的全部字符都不存在於string中,則返回0。

[root@xuexi ~]# expr index abcde 1
0

[root@xuexi ~]# expr index abcde 1x
0

(3)."substr string pos len"用法示例。

該表達式是從string中取出從pos位置開始長度爲len的子字符串。若是pos或len爲非正整數時,將返回空字符串。

[root@xuexi ~]# expr substr abcde 2 3
bcd

[root@xuexi ~]# expr substr abcde 2 4
bcde

[root@xuexi ~]# expr substr abcde 2 5
bcde

[root@xuexi ~]# expr substr abcde 2 0

[root@xuexi ~]# expr substr abcde 2 -1

(4)."length string"用法示例。該表達式是返回string的長度,其中string不容許爲空,不然將報錯,因此能夠用來判斷變量是否爲空。

[root@xuexi ~]# expr length abcde
5

[root@xuexi ~]# expr length 111
3

[root@xuexi ~]# expr length $xxx
expr: syntax error

[root@xuexi ~]# if [ $? -ne 0 ];then echo '$xxx is null';fi
$xxx is null

(5)."+ token"用法示例。

expr中有些符號和關鍵字有特殊意義,如"match"、"index"、"length",若是要讓其成爲字符,使用該表達式將任意token強制解析爲普通字符串。

[root@xuexi ~]# expr index index d
expr: syntax error

[root@xuexi ~]# expr index length g
expr: syntax error

[root@xuexi ~]# expr index + length g
4

對值爲關鍵字的變量來講,則無所謂。

[root@xuexi ~]# len=lenght

[root@xuexi ~]# expr index $len g
4

(6).算術運算用法示例。

[root@xuexi ~]# expr 1 + 2
3

[root@xuexi ~]# a=3
[root@xuexi ~]# b=4

[root@xuexi ~]# expr $a + $b
7

[root@xuexi ~]# expr 4 + $a
7

[root@xuexi ~]# expr $a - $b
-1

算術乘法符號"*"由於是shell的元字符,因此要轉義,可使用引號包圍,或者使用反斜線。

[root@xuexi ~]# expr $a * $b
expr: syntax error

[root@xuexi ~]# expr $a '*' $b
12

[root@xuexi ~]# expr $a \* $b
12

[root@xuexi ~]# expr $b / $a    # 除法只能取整數
1

[root@xuexi ~]# expr $b % $a
1

任意操做符兩端都須要有空格,不然:

[root@xuexi ~]# expr 4+$a 
4+3

[root@xuexi ~]# expr 4 +$a
expr: syntax error

因爲expr在進行算術運算時,首先會將操做符兩邊的參數轉換爲整數,任意一端轉換失敗都將會報錯,因此能夠用來判斷參數或變量是否爲整數。

[root@xuexi ~]# expr $a + $c
expr: non-integer argument

[root@xuexi ~]# if [ $? != 0 ];then echo '$a or $c is non-integer';fi          
$a or $c is non-integer

(7).比較操做符< <= = == != >= >用法示例。其中"<"和">"是正則表達式正的錨定元字符,且"<"會被shell解析爲重定向符號,因此須要轉義或用引號包圍。

這些操做符會首先會將兩端的參數轉換爲數值,若是轉換成功,則採用數值比較,若是轉換失敗,則按照字符集的排序規則進行字符大小比較。比較的結果若爲true,則expr返回1,不然返回0。

[root@xuexi ~]# a=3

[root@xuexi ~]# expr $a = 1
0

[root@xuexi ~]# expr $a = 3
1

[root@xuexi ~]# expr $a \* 3 = 9
1

[root@xuexi ~]# expr abc \> ab
1

[root@xuexi ~]# expr akc \> ackd
1

(8).邏輯鏈接符號"&"和"|"用法示例。這兩個符號都須要轉義,或使用引號包圍。

如下是官方文檔中給出的解釋,但實際使用過程當中是不徹底正確的。

"&"表示若是兩個參數同時知足非空且非0,則返回第一個參數的值,不然返回0。且若是發現第一個參數爲空或0,則直接跳過第二個參數不作任何計算。

"|"表示若是第一個參數非空且非0,則返回第一個參數值,不然返回第二個參數值,但若是第二個參數爲空或爲0,則返回0。且若是發現第一個參數非空或非0,也將直接跳過第二個參數不作任何計算。

正確的應該是:

"&"表示若是兩個參數都非0,則返回第一個參數,不然返回0。但任意一個參數爲空,則expr報錯。除非空字符串使用引號包圍,則處理方法和0同樣。

"|"表示若是第一個參數非0,則返回第一個參數的值,不然返回第二個參數。但若是任意一個參數爲空,則expr報錯。除非空字符串使用引號包圍,則處理方法和0同樣。

[root@xuexi ~]# expr $abc '|' 1
expr: syntax error

[root@xuexi ~]# expr "$abc" '|' 1
1

[root@xuexi ~]# expr "$abc" '&' 1 
0

[root@xuexi ~]# expr $abc '&' 1 
expr: syntax error

[root@xuexi ~]# expr 0 '&' abc
0

[root@xuexi ~]# expr abc '&' 0
0

[root@xuexi ~]# expr abc '|' 0
abc

[root@xuexi ~]# expr 0 '|' abc  
abc

[root@xuexi ~]# expr abc '&' cde
abc

[root@xuexi ~]# expr abc '|' cde
abc
相關文章
相關標籤/搜索