shell腳本中的各種表達式介紹和使用

  • 2020 年 3 月 18 日
  • 筆記

#前言:在shell腳本中,有各種的表達式,包括有條件測試表達式,文件表達式,字元串表達式,整數表達式,接下來我們來了解一下他們的使用方法

1.條件測試表達式

#首先來看一下條件測試語法

#條件測試語法                        #說明  1.test <測試表達式>       test命令和後面<內容>之間至少有一個空格  2.[ <測試表達式> ]        單中括弧進行條件測試表達式,[]的邊界和內容之間至少要有一個空格  3.[[ <測試表達式> ]]      雙括弧,[[]]的邊界和內容也是要有空格  4.((<測試表達式>))        雙小括弧,兩端不用空格

#注意點

1、語法1中的test命令和語法2中的[]是等價的。語法3中的[[]]為擴展的test命令,語法4中的(())常用於計算    2、在[[]](雙中括弧)中可以使用通配符等進行模式匹配,這是其區別其他集中語法格式的地方    3、&&、||、>、<等操作符可以應用於[[]]中,但不能應用於[]中,在[]中一般用-a、-o、-gt(用於整數)、-lt(用於整數)代替上述操作符    4、對於整數的關係運算,也可以使用shell的算術運算符(())

 

#詳解

1.1.test條件測試的語法和使用

#查看幫助:man test

#介紹:test – check file types and compare values(檢查文件類型和比較值)

#語法格式: test <測試表達式>

#test的幫助文檔

[root@shell ~]# man test > 1.txt

[root@shell ~]# cat 1.txt 

TEST(1)                               User Commands                               TEST(1)        NAME         test - check file types and compare values    SYNOPSIS         test EXPRESSION         test           [ EXPRESSION ]         [ ]         [ OPTION    DESCRIPTION         Exit with the status determined by EXPRESSION.           --help display this help and exit           --version                output version information and exit           An  omitted  EXPRESSION defaults to false.  Otherwise, EXPRESSION is true or false         and sets exit status.  It is one of:           ( EXPRESSION )                EXPRESSION is true           ! EXPRESSION                EXPRESSION is false           EXPRESSION1 -a EXPRESSION2                both EXPRESSION1 and EXPRESSION2 are true           EXPRESSION1 -o EXPRESSION2                either EXPRESSION1 or EXPRESSION2 is true           -n STRING                the length of STRING is nonzero           STRING equivalent to -n STRING           -z STRING                the length of STRING is zero           STRING1 = STRING2                the strings are equal           STRING1 != STRING2                the strings are not equal           INTEGER1 -eq INTEGER2                INTEGER1 is equal to INTEGER2           INTEGER1 -ge INTEGER2                INTEGER1 is greater than or equal to INTEGER2           INTEGER1 -gt INTEGER2                INTEGER1 is greater than INTEGER2           INTEGER1 -le INTEGER2                INTEGER1 is less than or equal to INTEGER2           INTEGER1 -lt INTEGER2                INTEGER1 is less than INTEGER2           INTEGER1 -ne INTEGER2                INTEGER1 is not equal to INTEGER2           FILE1 -ef FILE2                FILE1 and FILE2 have the same device and inode numbers           FILE1 -nt FILE2                FILE1 is newer (modification date) than FILE2           FILE1 -ot FILE2                FILE1 is older than FILE2           -b FILE                FILE exists and is block special           -c FILE                FILE exists and is character special           -d FILE                FILE exists and is a directory           -e FILE                FILE exists           -f FILE                FILE exists and is a regular file           -g FILE                FILE exists and is set-group-ID           -G FILE                FILE exists and is owned by the effective group ID           -h FILE                FILE exists and is a symbolic link (same as -L)           -k FILE                FILE exists and has its sticky bit set           -L FILE                FILE exists and is a symbolic link (same as -h)           -O FILE                FILE exists and is owned by the effective user ID           -p FILE                FILE exists and is a named pipe           -r FILE                FILE exists and read permission is granted           -s FILE                FILE exists and has a size greater than zero           -S FILE                FILE exists and is a socket           -t FD  file descriptor FD is opened on a terminal           -u FILE                FILE exists and its set-user-ID bit is set           -w FILE                FILE exists and write permission is granted           -x FILE                FILE exists and execute (or search) permission is granted           Except for -h and -L, all FILE-related tests dereference symbolic  links.   Beware         that  parentheses  need  to be escaped (e.g., by backslashes) for shells.  INTEGER         may also be -l STRING, which evaluates to the length of STRING.           NOTE: [ honors the --help and --version options, but test does not.   test  treats         each of those as it treats any other nonempty STRING.           NOTE:  your  shell may have its own version of test and/or [, which usually super‐         sedes the version described here.  Please refer to your shell's documentation  for         details about the options it supports.           GNU  coreutils  online  help: <http://www.gnu.org/software/coreutils/> Report test         translation bugs to <http://translationproject.org/team/>    AUTHOR         Written by Kevin Braunsdorf and Matthew Bradburn.    COPYRIGHT         Copyright © 2013 Free Software Foundation, Inc.  License GPLv3+: GNU GPL version 3         or later <http://gnu.org/licenses/gpl.html>.         This  is  free  software: you are free to change and redistribute it.  There is NO         WARRANTY, to the extent permitted by law.    SEE ALSO         The full documentation for test is maintained as a Texinfo manual.   If  the  info         and test programs are properly installed at your site, the command                  info coreutils 'test invocation'           should give you access to the complete manual.        GNU coreutils 8.22                     August 2019                                TEST(1)

View Code

#使用

#例一:判斷如果file文件存在且為一個文件,就輸出true,否則輸出false

[root@shell ~]# test -f file && echo true || echo false  false

#講解:因為file這個文件不存在,所以輸出false,&&是並且的意思,||表示前面一個執行失敗才會執行後面

 

#例二:使用-z選項(如果測試字元串的長度為0,則表達式成立)

[root@shell ~]# test -z "guoke" && echo 1 || echo 0  0  #因為測試的字元串為guoke,不為空值,所以為假輸出0  [root@shell ~]# char="guoke"  [root@shell ~]# test -z "$char" && echo 1 || echo 0  0  #因為guoke賦值給了char,所以也不是空值,輸出0  [root@shell ~]# char=""  [root@shell ~]# test -z "$char" && echo 1 || echo 0  1  #char為空值,所以長度為0,表達式成立輸出1

 

1.2.[]中括弧條件測試語法和使用

#語法格式:[ <測試表達式> ]

#注意點:中括弧內部的兩端都要有空格,[]和test用法一樣,test的判斷選項也可以在[]中用

#輸入兩端都有空格的技巧:先輸入一對中括弧,然後退一個格,輸入兩個空格,再退一個格

#例子:利用[]加-f選項(如果文件存在且為普通文件則表達式就成立)

[root@shell ~]# [ -f /tmp/guoke.txt ] && echo 1 || echo 0  0  #文件不存在所以輸出0  [root@shell ~]# touch /tmp/guoke.txt  [root@shell ~]# [ -f /tmp/guoke.txt ] && echo 1 || echo 0  1  #文件存在且為一個普通文件,則輸出1  [root@shell ~]# [ -f /tmp/guoke.txt ] && echo 1  1

 

1.3.[[]] 雙中括弧條件測試語法及使用

#語法格式:[[ <測試表達式> ]]

#注意點:雙中括弧的兩端需要有空格

#例子:判斷文件存在且為一個普通文件

[root@shell ~]# [[ -f /tmp/test.txt ]] && echo 1 || echo 0  0  #文件不存在所以條件不成立,輸出0  [root@shell ~]# touch /tmp/test.txt  [root@shell ~]# [[ -f /tmp/test.txt ]] && echo 1 || echo 0  1  #文件存在且為普通文件,條件成立,輸出1  [root@shell ~]# [[ -f /tmp/test.txt ]] && echo 1  1

 

1.4.特殊條件測試表達式例子

#判斷條件測試表達式的條件成立或不成立後,還需要執行多條命令語句的語法,不用if測試表達式的格式

#當條件1成立時,同時執行多條命令

test 條件1 && {    }    [ 條件1 ] && {      命令1      命令2    }  [[ 條件1 ]] && {    }

#例子:當條件成立的時候就執行後面的命令

[root@shell ~]# cat test.sh  #!/bin/bash  [ $1 -eq 3 ] && {      echo 1      echo 2      echo 3  }    [root@shell ~]# sh test.sh 3 #傳參  1  2  3

#上面的判斷相當於下面if語句的效果

if [ 條件1 ];then      命令1      命令2  fi

 

#關於條件測試表達式的總結

#1.test和[]、[[]]的功能有所重合,因此在工作中選擇一種適合自己的一種用,其他的可以看懂別人的寫的腳本就好了,可以同man test查看更多參數用法

#2.測試表達式test、[]、[[]]、(())區別總結

測試表達式符號            test             []             [[]]          (())  邊界是否需要空格          需要              需要            需要         不需要  邏輯操作符              !、-a、-o        !、-a、-o       !、&&、||     !、&&、||  整數比較操作符            -eq -gt -lt -ge -le(test,[],[[]])          = < > >= <=  字元串比較操作符           =、==、!= (全部支援)  是否支援通配符匹配        不支援          不支援            支援         不支援

 

2.文件表達式

#常用的文件測試操作符

#常用操作符                        #說明  -f 文件,全稱file            #文件存在且為普通文件則為真,表達式成立  -d 文件,全稱directory       #文件存在且為目錄則為真,表達式成立  -s 文件,全稱size            #文件存在且大小不為0為真  -e 文件,全稱exist           #文件存在則為真  -r 文件,全稱read            #文件存在且為可讀則為真,表達式成立  -w 文件,全稱write           #文件存在且可寫為真,表達式成立  -x 文件,全稱executable      #文件存在且可執行為真  -L 文件,全稱link            #文件存在且為鏈接文件為真  f1 -nt f2,英文newer than    #文件f1比文件f2新則為真,根據文件修改時間計算  f1 -ot f2,英文older than    #文件f1比文件f2舊為真,根據修改時間計算

 #提示:這些操作符對於test,[],[[]]幾乎是通用的,可以使用man test查看更多的操作符

#例子:

 #1.-f,判斷文件是否存在且為普通文件

[root@shell ~]# touch test  [root@shell ~]# ls -l test  -rw-r--r-- 1 root root 0 Mar 18 16:02 test  [root@shell ~]# [ -f test ] && echo 1 || echo 0  1   #解析:因為文件存在且為普通文件,所以為真輸出1

 

#2.-d,判斷文件是否存在且為目錄

[root@shell ~]# mkdir test1  [root@shell ~]# [ -d test1 ] && echo 1 || echo 0  1  #因為文件存在且為目錄,所以為真輸出1,如果不存在就輸出0

 

#3.測試文件屬性:r,w,x

[root@shell ~]# ls -ld test  -rw-r--r-- 1 root root 0 Mar 18 16:02 test  [root@shell ~]# [ -r test ] && echo 1 || echo 0  1   #文件存在且可讀,為真,輸出1  [root@shell ~]# [ -w test ] && echo 1 || echo 0  1   #文件存在且可寫,為真,輸出1  [root@shell ~]# [ -x test ] && echo 1 || echo 0  0  #文件不可執行,不為真,所以輸出0  [root@shell ~]# chmod +x test  [root@shell ~]# [ -x test ] && echo 1 || echo 0  1   #加了可執行許可權就為真成立了

#提示:測試文件的讀、寫、執行等屬性,不光是根據文件屬性rwx的標識來判斷,還要看當前執行測試的用戶是否真的可以按照對應的許可權操作該文件

 

#測試時變數的特殊寫法及問題

#用[]測試變數時,如果被測試的變數不加雙引號,那麼測試結果可能會是不正確的

#例子

[root@shell ~]# echo $test  #不存在的變數    [root@shell ~]# [ -f $test ] && echo 1 || echo 0 #不加引號返回的結果時錯誤的  1  [root@shell ~]# [ -f "$test" ] && echo 1 || echo 0 #添加以後返回的結果是正確的  0 

 

#注意點:做測試判斷時,不一定非要按照前面的如果成立了輸出什麼,不成立輸出什麼,可以直接做部分判斷

[root@shell ~]# [ -x test ] && echo 1  #如果test文件可執行,就輸出1,否則不做任何輸出  [root@shell ~]# [ -f /etc ] || echo 0  #如果前面執行失敗就輸出0,否則不做任何輸出  0

 

3.字元串表達式

#字元串表達式作用:比較兩個字元串是否相同、測試字元串的長度是否為0、字元串是否為null等

#常用的字元串測試操作符

#常用字元串操作符                #說明  -z "字元串"                    如果字元串長度為0則為真,  -n "字元串"                    如果字元串長度不為0則為真,  "字元串1" = "字元串2"           如果字元串1等於字元串2則為真,可以使用==代替=  "字元串1" != "字元串2"          如果字元串1不等於字元串2則為真,不能使用!==代替!=

 #提示:

#1.上面的字元串測試操作符必須要有””引起來

#2.比較符號兩端要有空格

#3.-n 比較字元串長度是否不為0,如果不為0則為真,用法 [ -n “$my” ]

#4.-z 比較字元串長度是否為0,如果為0則為真,用法 [ -z “$my” ]

 #例1:-n,-z參數應用

[root@shell ~]# [ -n "abc" ] && echo 1 || echo 0  1    #-n是不為空則為真,字元串長度為abc,所以長度不是為0,為真輸出1  [root@shell ~]# test -n "aa" && echo 1 || echo 0  1  [root@shell ~]# test -n "" && echo 1 || echo 0  0    #字元串為空,不為真,數以輸出0  [root@shell ~]# var="test"  [root@shell ~]# [ -n "$var" ] && echo 1|| echo 0  1  [root@shell ~]# [ -z "$var" ] && echo 1|| echo 0  0    #-z是為空值為真,不為空值為假,所以輸出0,  [root@shell ~]# [ "aa" = "aa" ] && echo 1 || echo 0  1    #字元串相等,所以長度為0,為真

 

#例二:進行字元串比較時,如果等號兩端沒有空格帶來的問題

[root@shell ~]# [ "abc"="1" ]&& echo 1 || echo 0  1     #等號兩邊沒有空格,明顯是不成立的也輸出了1  [root@shell ~]# [ "abc" = "1" ]&& echo 1 || echo 0  0    #正常現象

 

#總結:字元串比較時若等號兩端沒有空格,則會導致判斷出現邏輯錯誤,即使語句沒有問題,但是結果依然可能不對

 

#例三:字元串不加引號可能帶來的問題

[root@shell ~]# var=""    #將變數內容設置為空  [root@shell ~]# [ -n "$var" ] && echo 1 || echo 0  0    #-n是值不為空則為真,因為變數內容為0,為空值,所以不為真,輸出0  [root@shell ~]# [ -n $var ] && echo 1 || echo 0  1    #不加雙引號導致返回結果錯誤  [root@shell ~]# [ -z "$var" ]&& echo 1 || echo 0  1    #-z是字元串長度為0,則為真

 

#查看有關雙引號和等號兩端空格的生產系統標準

[root@shell ~]# sed -n '30,31p' /etc/init.d/network  # Check that networking is up.  [ "${NETWORKING}" = "no" ] && exit 6

 

4.整數表達式

#整數二元比較操作符

在test及[]中使用的比較符號    在[[]]和(())中使用的比較符號        說明  -eq                            == 或 =                 相等,全稱equal  -ne                              !=                   不相等,全稱not qeual  -gt                               >                   大於,全稱greater than  -ge                               >=                  大於等於,全稱為greater equal  -lt                               <                   小於,全稱less than  -le                               <=                  小於等於,全稱less equal                              

 #提示:如果選擇整數比較的時候,要確保兩邊是整數,如[ 2 -eq 1 ]

 #注意:”<“和”>”在[]中括弧裡面需要轉義,對於數字不轉義的結果可能不會報錯,但是結果可能不對,=和!=在[]不用轉義

#例子

[root@shell ~]# [ 2 > 3 ] && echo 1 || echo 0  1 #結果應該返回0,但是不轉義返回了1是錯誤的  [root@shell ~]# [ 2 > 3 ] && echo 1 || echo 0  0 #進行轉義之後輸出正確  [root@shell ~]# [ 2 < 1 ] && echo 1 || echo 0  1  [root@shell ~]# [ 2 < 1 ] && echo 1 || echo 0  0

 

 #整數比較的推薦用法,使用-eq,-lt,-gt

#例子

[root@shell ~]# [ 13 -lt 24 ] && echo 1  1  #13小於24結果為真就輸出1

 

5.邏輯操作符

#常用的邏輯操作符

在test及[]中使用的比較符號    在[[]]和(())中使用的比較符號        說明      -a                              &&                     and,且,兩端都為真,則結果為真      -o                              ||                     or,或,兩端有一個為真,則結果為真       !                               !                     not,非,兩端相反,則結果為真

#提示

1、邏輯操作符前後的表達式是否成立,一般用真假來表示  2、“!”的中文意思是反,即與一個邏輯值相反的邏輯值  3、-a的中文意思是“與”(and或&&),前後兩個邏輯值都為“真”,綜合返回值才為真,否則為假  4、-o的中文意思是“或”(or或||),前後兩個邏輯值只要有一個為真,返回值就為真  5、連接兩行[]、test或[[]]的表達式可用&&或||

 #提示:中括弧裡面不能使用&&字元串,否則報錯,在[[]]和(())裡面就可以用,可參考上面列出的

[root@shell ~]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0  -bash: [: missing `]'  0

 

#例一:

[root@shell ~]# f1=/etc/rc.local  [root@shell ~]# f2=/etc/services  [root@shell ~]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0  1  #判斷如果f2和f2變數的文件存在且為文件的話,就為真,輸出1,如果一個不為真,那麼久不為真,就輸出0  [root@shell ~]# [[ -f "$f1" && -f "$f2" ]] && echo 1 || echo 0   1  #在[[]]雙中括弧中就可以使用&&  [root@shell ~]# [ -f "$f1" ]&&[ -f "$f2" ] && echo 1 || echo 0  1  #或者在兩個[]之間使用&&也可以

 

 #例二:

[root@shell ~]# a=1  [root@shell ~]# b=2  [root@shell ~]# [ "$a" -eq 2 -a "$b" -eq 2 ] && echo 1 || echo 0  0    #如果變數a等於2且變數b也等於2,則為真,否則為假,輸出0  [root@shell ~]# [ "$a" -eq 1 -a "$b" -eq 2 ] && echo 1 || echo 0  1  [root@shell ~]# [ "$a" -eq 1 -o "$b" -eq 2 ] && echo 1 || echo 0  1    #如果變數a等於或變數b等於2,則為真,輸出1,-o是或,有一個條件成立則為真  [root@shell ~]# [ "$a" -eq 2 -o "$b" -eq 3 ] && echo 1 || echo 0  0