SHELL指令碼攻略(學習筆記)--1.7 expr命令全解,--1.7expr

來源:互聯網
上載者:User

SHELL指令碼攻略(學習筆記)--1.7 expr命令全解,--1.7expr

expr命令可以實現數值運算、數值或字串比較、字串匹配、字串提取、字串長度計算等功能。它還具有幾個特殊功能,判斷變數或參數是否為整數、是否為空白、是否為0等。

先看expr命令的info文檔info coreutils 'expr invocation'的翻譯。

16.4.1 字串運算式-------------------------'expr'支援模式比對和字串操作。字串運算式的優先順序高於數值運算式和邏輯關聯運算式。 'STRING : REGEX'     執行模式比對。兩端參數會轉換為字元格式設定,且第二個參數被視為     Regex(GUN基本正則),它預設會隱含首碼"^"。隨後將第一個參數     和正則模式做匹配。      如果匹配成功,且REGEX使用了'\('和'\)',則才運算式返回匹配到的      如果匹配失敗,如果REGEX中使用了'\('和'\)',則此運算式返回Null 字元     串,否則返回為0。      只有第一個'\(...\)'會引用返回的值;其餘的'\(...\)'只在Regex     分組時有意義。      在Regex中,'\+','\?'和'\|'分表代表匹配一個或多個,0個或1個     以及兩端任選其一的意思。 'match STRING REGEX'     等價於'STRING : REGEX'。 'substr STRING POSITION LENGTH'     返回STRING字串中從POSITION開始,長度最大為LENGTH的子串。如果     POSITION或LENGTH為負數,0或非數值,則返回Null 字元串。 '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,則     返回第一個參數的值,否則返回第二個參數。但如果任意一個參數為空白,則報錯。     除非Null 字元串使用引號包圍,此時將和0的處理方式一樣。 '&'     如果兩個參數都非空且非0,則返回第一個參數,否則返回0。如果第一個參     為0或為空白,則不會計算第二個參數。         經過測試,以上手冊內容是錯誤的。正確的應該是:如果兩個參數都非0,則     返回第一個參數,否則返回0。但任意一個參數為空白,則報錯。除非Null 字元串     使用引號包圍,此時將和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

下面將使用樣本來介紹expr的用法,在介紹之前,需要注意三點:

(1).數值運算式("+ - * / %")和比較運算式("< <= = == != >= >")會先將兩端的參數轉換為數值,轉換失敗將報錯。所以可藉此來判斷參數或變數是否為整數。

(2).expr中的很多符號需要轉義或使用引號包圍。

(3).所有操作符的兩邊,都需要有空格。

以下是expr樣本。

(1)."string : REGEX"字串匹配樣本。要輸出匹配到的字串結果,需要使用"\("和"\)",否則返回的將是匹配到的字串數量。

[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首字元開始的。

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

之所以為0,是因為真正的Regex是"^cd.*",而abcde不是c開頭而是a開頭的,所以無法匹配到任何結果。因此,任何字串匹配時,都應該從首字元開始。

字串匹配時,會先將兩端參數轉換為字元格式設定。

(2)."index string chars"用法樣本。

該運算式是從string中搜尋chars中某個字元的位置,這個字元是string中最靠前的字元。例如:

[root@xuexi ~]# expr index abcde dec3

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

[root@xuexi ~]# expr index abcde xdc3

如果chars中的所有字元都不存在於string中,則返回0。

[root@xuexi ~]# expr index abcde 10[root@xuexi ~]# expr index abcde 1x0

(3)."substr string pos len"用法樣本。

該運算式是從string中取出從pos位置開始長度為len的子字串。如果pos或len為非正整數時,將返回Null 字元串。

[root@xuexi ~]# expr substr abcde 2 3bcd[root@xuexi ~]# expr substr abcde 2 4bcde[root@xuexi ~]# expr substr abcde 2 5bcde[root@xuexi ~]# expr substr abcde 2 0[root@xuexi ~]# expr substr abcde 2 -1

(4)."length string"用法樣本。該運算式是返回string的長度,其中string不允許為空白,否則將報錯,所以可以用來判斷變數是否為空白。

[root@xuexi ~]# expr length abcde5[root@xuexi ~]# expr length 1113[root@xuexi ~]# expr length $xxxexpr: 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 dexpr: syntax error[root@xuexi ~]# expr index length gexpr: syntax error[root@xuexi ~]# expr index + length g4

其實可以通過字串匹配的方式,將關鍵字轉換為字串。例如:

[root@xuexi ~]# expr index 'length : "\(length\)"' g 4

對值為關鍵字的變數來說,則無所謂。

[root@xuexi ~]# len=lenght[root@xuexi ~]# expr index $len g4

(6).算術運算用法樣本。

[root@xuexi ~]# expr 1 + 23[root@xuexi ~]# a=3[root@xuexi ~]# b=4[root@xuexi ~]# expr $a + $b7[root@xuexi ~]# expr 4 + $a7[root@xuexi ~]# expr $a - $b-1

算術乘法符號"*"因為是Regex中的元字元,所以要轉義,可以使用引號包圍,或者使用反斜線。

[root@xuexi ~]# expr $a * $bexpr: syntax error[root@xuexi ~]# expr $a '*' $b12[root@xuexi ~]# expr $a \* $b12[root@xuexi ~]# expr $b / $a    # 除法只能取整數1[root@xuexi ~]# expr $b % $a1

任意操作符兩端都需要有空格,否則:

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

由於expr在進行算術運算時,首先會將操作符兩邊的參數轉換為整數,任意一端轉換失敗都將會報錯,所以可以用來判斷參數或變數是否為整數。

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

(7).比較操作符< <= = == != >= >用法樣本。其中"<"和">"是Regex正的錨定元字元,且"<"會被shell解析為重新導向符號,所以需要轉義或用引號包圍。

這些操作符會首先會將兩端的參數轉換為數值,如果轉換成功,則採用數值比較,如果轉換失敗,則按照字元集的定序進行字元大小比較。比較的結果若為true,則expr返回1,否則返回0。

[root@xuexi ~]# a=3[root@xuexi ~]# expr $a = 10[root@xuexi ~]# expr $a = 31[root@xuexi ~]# expr $a \* 3 = 91[root@xuexi ~]# expr abc \> ab1[root@xuexi ~]# expr akc \> ackd1

(8).邏輯串連符號"&"和"|"用法樣本。這兩個符號都需要轉義,或使用引號包圍。

以下是官方文檔中給出的解釋,但實際使用過程中是不完全正確的。

"&"表示如果兩個參數同時滿足非空且非0,則返回第一個參數的值,否則返回0。且如果發現第一個參數為空白或0,則直接跳過第二個參數不做任何計算。

"|"表示如果第一個參數非空且非0,則返回第一個參數值,否則返回第二個參數值,但如果第二個參數為空白或為0,則返回0。且如果發現第一個參數非空或非0,也將直接跳過第二個參數不做任何計算。

正確的應該是:

"&"表示如果兩個參數都非0,則返回第一個參數,否則返回0。但任意一個參數為空白,則expr報錯。除非Null 字元串使用引號包圍,則處理方法和0一樣。

"|"表示如果第一個參數非0,則返回第一個參數的值,否則返回第二個參數。但如果任意一個參數為空白,則expr報錯。除非Null 字元串使用引號包圍,則處理方法和0一樣。

[root@xuexi ~]# expr $abc '|' 1expr: syntax error[root@xuexi ~]# expr "$abc" '|' 11[root@xuexi ~]# expr "$abc" '&' 1 0[root@xuexi ~]# expr $abc '&' 1 expr: syntax error[root@xuexi ~]# expr 0 '&' abc0[root@xuexi ~]# expr abc '&' 00[root@xuexi ~]# expr abc '|' 0abc[root@xuexi ~]# expr 0 '|' abc  abc[root@xuexi ~]# expr abc '&' cdeabc[root@xuexi ~]# expr abc '|' cdeabc

 

回到系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html

轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/7231832.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.