C語言中文網 目錄
Shell腳本
1 Shell是什么
2 Shell是運維人員必須掌握的技能
3 常用的Shell有哪些
4 進入Shell的兩種方式
5 Shell命令的基本格式
6 Shell命令的本質到底是什么?如何自己實現一個命令?
7 Shell命令的選項和參數在本質上是什么
8 Shell命令提示符
9 修改命令提示符
10 第一個Shell腳本
11 執行Shell腳本
12 Shell四種運行方式(啟動方式)
13 Shell配置文件(配置腳本)的加載
14 如何編寫自己的Shell配置文件?
15 Shell變量
16 Shell變量的作用域
17 Shell命令替換
18 Shell位置參數
19 Shell特殊變量
20 Shell $*和$@的區別
21 Shell $?
22 Shell字符串詳解
23 Shell字符串拼接
24 Shell字符串截取
25 Shell數組
26 Shell獲取數組長度
27 Shell數組拼接
28 Shell刪除數組元素
29 Shell關聯數組
30 Shell內建命令
31 Shell alias命令
32 Shell echo命令
33 Shell read命令
34 Shell exit命令
35 Shell declare和typeset命令
36 Shell數學計算
37 Shell (())
38 Shell let命令
39 Shell $[]
40 Shell expr命令
41 Linux bc命令
42 Shell declare -i
43 Shell if else
44 Shell退出狀態
45 Shell test命令
46 Shell [[]]
47 Shell case in
48 Shell while
49 Shell until
50 Shell for
51 Shell select in
52 Shell break和continue
53 Shell函數
54 Shell函數參數
55 Shell函數返回值精講
56 Shell重定向
57 Linux中的文件描述符到底是什么?
58 結合文件描述符談重定向,徹底理解重定向的本質!
59 使用exec命令操作文件描述符
60 Shell代碼塊重定向
61 Shell Here Document
62 Shell Here String
63 Shell組命令
64 Shell進程替換
65 Linux管道
66 子Shell和子進程到底有什么區別?
67 如何檢測子Shell和子進程?
68 Shell過濾器
69 Linux中的信號
70 Bash Shell中的信號
71 Linux進程是什么
72 Shell模塊化(把代碼分散到多個腳本文件中)
首頁 > Shell腳本 閱讀:2,427

Shell test命令(Shell [])詳解,附帶所有選項及說明

< 上一頁Shell退出狀態 Shell [[]]下一頁 >

test 是 Shell 內置命令,用來檢測某個條件是否成立。test 通常和 if 語句一起使用,并且大部分 if 語句都依賴 test。

test 命令有很多選項,可以進行數值、字符串和文件三個方面的檢測。

Shell test 命令的用法為:

test expression

當 test 判斷 expression 成立時,退出狀態為 0,否則為非 0 值。

test 命令也可以簡寫為[],它的用法為:

[ expression ]

注意[]expression之間的空格,這兩個空格是必須的,否則會導致語法錯誤。[]的寫法更加簡潔,比 test 使用頻率高。
test 和 [] 是等價的,后續我們會交替使用 test 和 [],以讓讀者盡快熟悉。
在《Shell if else》中,我們使用 (()) 進行數值比較,這節我們就來看一下如何使用 test 命令進行數值比較。
#!/bin/bash

read age

if test $age -le 2; then
    echo "嬰兒"
elif test $age -ge 3 && test $age -le 8; then
    echo "幼兒"
elif [ $age -ge 9 ] && [ $age -le 17 ]; then
    echo "少年"
elif [ $age -ge 18 ] && [ $age -le 25 ]; then
    echo "成年"
elif test $age -ge 26 && test $age -le 40; then
    echo "青年"
elif test $age -ge 41 && [ $age -le 60 ]; then
    echo "中年"
else
    echo "老年"
fi
其中,-le選項表示小于等于,-ge選項表示大于等于,&&是邏輯與運算符。

學習 test 命令,重點是學習它的各種選項,下面我們就逐一講解。

1) 與文件檢測相關的 test 選項

表1:test 文件檢測相關選項列表
文件類型判斷
選 項 作 用
-b filename 判斷文件是否存在,并且是否為塊設備文件。
-c filename 判斷文件是否存在,并且是否為字符設備文件。
-d filename 判斷文件是否存在,并且是否為目錄文件。
-e filename 判斷文件是否存在。
-f filename 判斷文件是否存在,井且是否為普通文件。
-L filename 判斷文件是否存在,并且是否為符號鏈接文件。
-p filename 判斷文件是否存在,并且是否為管道文件。
-s filename 判斷文件是否存在,并且是否為非空。
-S filename 判斷該文件是否存在,并且是否為套接字文件。
文件權限判斷
選 項 作 用
-r filename 判斷文件是否存在,并且是否擁有讀權限。
-w filename 判斷文件是否存在,并且是否擁有寫權限。
-x filename 判斷文件是否存在,并且是否擁有執行權限。
-u filename 判斷文件是否存在,并且是否擁有 SUID 權限。
-g filename 判斷文件是否存在,并且是否擁有 SGID 權限。
-k filename 判斷該文件是否存在,并且是否擁有 SBIT 權限。
文件比較
選 項 作 用
filename1 -nt filename2 判斷 filename1 的修改時間是否比 filename2 的新。
filename -ot filename2 判斷 filename1 的修改時間是否比 filename2 的舊。
filename1 -ef filename2 判斷 filename1 是否和 filename2 的 inode 號一致,可以理解為兩個文件是否為同一個文件。這個判斷用于判斷硬鏈接是很好的方法

Shell test 文件檢測舉例:
#!/bin/bash

read filename
read url

if test -w $filename && test -n $url
then
    echo $url > $filename
    echo "寫入成功"
else
    echo "寫入失敗"
fi
Shell 腳本文件所在的目錄新建一個文本文件并命名為 urls.txt,然后運行 Shell 腳本,運行結果為:
urls.txt↙
http://www.frifeb11.com/shell/↙
寫入成功

2) 與數值比較相關的 test 選?項

表2:test 數值比較相關選項列表
選 項 作 用
num1 -eq num2 判斷 num1 是否和 num2 相等。
num1 -ne num2 判斷 num1 是否和 num2 不相等。
num1 -gt num2 判斷 num1 是否大于 num2 。
num1 -lt num2 判斷 num1 是否小于 num2。
num1 -ge num2 判斷 num1 是否大于等于 num2。
num1 -le num2 判斷 num1 是否小于等于 num2。

注意,test 只能用來比較整數,小數相關的比較還得依賴 bc 命令

Shell test 數值比較舉例:
#!/bin/bash

read a b

if test $a -eq $b
then
    echo "兩個數相等"
else
    echo "兩個數不相等"
fi
運行結果1:
10 10
兩個數相等

運行結果2:
10 20
兩個數不相等

3) 與字符串判斷相關的 test 選項

表3:test 字符串判斷相關選項列表
選 項 作 用
-z str 判斷字符串 str 是否為空。
-n str 判斷宇符串 str 是否為非空。
str1 = str2
str1 == str2
===是等價的,都用來判斷 str1 是否和 str2 相等。
str1 != str2 判斷 str1 是否和 str2 不相等。
str1 \> str2 判斷 str1 是否大于 str2。\>>的轉義字符,這樣寫是為了防止>被誤認為成重定向運算符。
str1 \< str2 判斷 str1 是否小于 str2。同樣,\<也是轉義字符。

C語言C++PythonJava 等編程經驗的讀者請注意,==、>、< 在大部分編程語言中都用來比較數字,而在 Shell 中,它們只能用來比較字符串,不能比較數字,這是非常奇葩的,大家要習慣。

其次,不管是比較數字還是字符串,Shell 都不支持 >= 和 <= 運算符,切記。

Shell test 字符串比較舉例:
#!/bin/bash

read str1
read str2

#檢測字符串是否為空
if [ -z "$str1" ] || [ -z "$str2" ]
then
    echo "字符串不能為空"
    exit 0
fi

#比較字符串
if [ $str1 = $str2 ]
then
    echo "兩個字符串相等"
else
    echo "兩個字符串不相等"
fi
運行結果:
http://www.frifeb11.com/
http://www.frifeb11.com/shell/
兩個字符串不相等

細心的讀者可能已經注意到,變量 $str1 和 $str2 都被雙引號包圍起來,這樣做是為了防止 $str1 或者 $str2 是空字符串時出現錯誤,本文的后續部分將為你分析具體原因。

4) 與邏輯運算相關的 test 選項

表4:test 邏輯運算相關選項列表
選 項 作 用
expression1 -a expression 邏輯與,表達式 expression1 和 expression2 都成立,最終的結果才是成立的。
expression1 -o expression2 邏輯或,表達式 expression1 和 expression2 有一個成立,最終的結果就成立。
!expression 邏輯非,對 expression 進行取反。

改寫上面的代碼,使用邏輯運算選項:
#!/bin/bash

read str1
read str2

#檢測字符串是否為空
if [ -z "$str1" -o -z "$str2" ]  #使用 -o 選項取代之前的 ||
then
    echo "字符串不能為空"
    exit 0
fi

#比較字符串
if [ $str1 = $str2 ]
then
    echo "兩個字符串相等"
else
    echo "兩個字符串不相等"
fi
前面的代碼我們使用兩個[]命令,并使用||運算符將它們連接起來,這里我們改成-o選項,只使用一個[]命令就可以了。

在 test 中使用變量建議用雙引號包圍起來

test 和 [] 都是命令,一個命令本質上對應一個程序或者一個函數。即使是一個程序,它也有入口函數,例如C語言程序的入口函數是 main(),運行C語言程序就從 main() 函數開始,所以也可以將一個程序等效為一個函數,這樣我們就不用再區分函數和程序了,直接將一個命令和一個函數對應起來即可。

有了以上認知,就很容易看透命令的本質了:使用一個命令其實就是調用一個函數,命令后面附帶的選項和參數最終都會作為實參傳遞給函數。

假設 test 命令對應的函數是 func(),使用test -z $str1命令時,會先將變量 $str1 替換成字符串:
  • 如果 $str1 是一個正常的字符串,比如 abc123,那么替換后的效果就是test -z abc123,調用 func() 函數的形式就是func("-z abc123")。test 命令后面附帶的所有選項和參數會被看成一個整體,并作為實參傳遞進函數。
  • 如果 $str1 是一個空字符串,那么替換后的效果就是test -z ,調用 func() 函數的形式就是func("-z "),這就比較奇怪了,因為-z選項沒有和參數成對出現,func() 在分析時就會出錯。

如果我們給 $str1 變量加上雙引號,當 $str1 是空字符串時,test -z "$str1"就會被替換為test -z "",調用 func() 函數的形式就是func("-z \"\""),很顯然,-z選項后面跟的是一個空字符串(\"表示轉義字符),這樣 func() 在分析時就不會出錯了。

所以,當你在 test 命令中使用變量時,我強烈建議將變量用雙引號""包圍起來,這樣能避免變量為空值時導致的很多奇葩問題。

總結

test 命令比較奇葩,>、<、== 只能用來比較字符串,不能用來比較數字,比較數字需要使用 -eq、-gt 等選項;不管是比較字符串還是數字,test 都不支持 >= 和 <=。有經驗的程序員需要慢慢習慣 test 命令的這些奇葩用法。

對于整型數字的比較,我建議大家使用 (()),這在《Shell if else》中已經進行了演示。(()) 支持各種運算符,寫法也符合數學規則,用起來更加方便,何樂而不為呢?

幾乎完全兼容 test ,并且比 test 更加強大,比 test 更加靈活的是[[ ]][[ ]]不是命令,而是 Shell 關鍵字,下節《Shell [[]]》我們將會講解。
< 上一頁Shell退出狀態 Shell [[]]下一頁 >

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo