Shell 運算符
1. Shell 運算符概述
1.1 Shell 運算符是什么
與其他語言一樣,Shell 也有運算符,在 Shell 中其根據(jù)類型不同也有不少運算符分類,那么什么是運算符呢?例如大家都知道在算術運算中的加減乘除,+
就是我們 Shell 中的算術運算符的一種,當然還有很多其他的功能各異的運算符,作為條件判斷與算術操作等重要功能,構成了 Shell 中的基本元素。
1.2 為什么要用運算符
當我們對數(shù)值進行算術運算,當我們需要對文件進行判斷,當我們需要多邏輯進行判斷的時候,這些情況都需要使用不同類型的運算符,使得我們腳本更為靈活便捷。
2. Shell 運算符分類
我們知道了 shell 中運算符是什么及其功能,接下來讓我們看一下 Shell 腳本運算符的分類及每種運算符的基本操作。
2.1 算術運算符
算術運算符顧名思義,其就是進行加減乘除數(shù)值運算,在 shell 中,bash 不支持原生的數(shù)學運算,需要利用第三方工具來如 let
,expr
等來實現(xiàn)。
運算符 | 說明 | 舉例 |
---|---|---|
+ | 加法 | expr $a + $b 結果為 30。 |
- | 減法 | expr $a - $b 結果為 -10。 |
* | 乘法 | expr $a \* $b 結果為 200。 |
/ | 除法 | expr $b / $a 結果為 2。 |
% | 取余 | expr $b % $a 結果為 0。 |
= | 賦值 | a=$b 將把變量 b 的值賦給 a。 |
== | 相等 | 用于比較兩個數(shù)字,相同則返回 true。 [$a == $b] 返回 false。 |
!= | 不相等 | 用于比較兩個數(shù)字,不相同則返回 true。 [$a != $b] 返回 true。 |
2.1.1 let
可以利用 let
對數(shù)值進行運算,let C=$A+$B
, 例如:
[root@master ~]# A=1
[root@master ~]# B=2
[root@master ~]# let C=${A}+${B}
[root@master ~]# echo $C
3
注意:let
運算后需要將其賦值給一個變量。
2.1.2 expr
可以利用 expr
對數(shù)組進行運算,C=$(expr $A+$B)
,例如:
[root@master ~]# C=`expr $A + $B`
[root@master ~]# echo $C
3
注意 +
號兩邊需要有空格,不然會將其當作字符串連接
2.1.3 []
可以利用 []
來對數(shù)值進行運算,C=[A+B]
,例如:
[root@master ~]# C=$[$A+$B]
[root@master ~]# echo $C
3
2.1.4 (())
利用 (())
來對數(shù)值進行運算,C=$(($A+$B))
,例如:
[root@master ~]# C=$(($A+$B))
[root@master ~]# echo $C
3
2.2 關系運算符
了解了算術運算,接下來讓我們學習關系運算。
比較符 | 描述 | 示例 |
---|---|---|
-eq,equal | 等于 | [1 -eq 1] 為 true |
-ne,not equal | 不等于 | [1 -ne 1] 為 false |
-gt,greater than | 大于 | [2 -gt 1] 為 true |
-lt,lesser than | 小于 | [2 -lt 1] 為 false |
-ge,greater or equal | 大于或等于 | [2 -ge 1] 為 true |
-le,lesser or equal | 小于或等于 | [2 -le 1] 為 false |
關系運算顧名思義就是比較數(shù)字的大小,注意關系運算符作用的為數(shù)字,不能用其來比較字符串。
#!/bin/bash
num1=1
num2=2
echo "num1 為:${num1}"
echo "num2 為:${num2}"
if [ $num1 -eq $num2 ]
then
echo "$num1 -eq $num2 : num1 等于 num2"
else
echo "$num1 -eq $num2: num1 不等于 num2"
fi
if [ $num1 -ne $num2 ]
then
echo "$num1 -ne $num2: num1 不等于 num2"
else
echo "$num1 -ne $num2 : num1 等于 num2"
fi
if [ $num1 -gt $num2 ]
then
echo "$num1 -gt $num2: num1 大于 num2"
else
echo "$num1 -gt $num2: num1 不大于 num2"
fi
if [ $num1 -lt $num2 ]
then
echo "$num1 -lt $num2: num1 小于 num2"
else
echo "$num1 -lt $num2: num1 不小于 num2"
fi
if [ $num1 -ge $num2 ]
then
echo "$num1 -ge $num2: num1 大于或等于 num2"
else
echo "$num1 -ge $num2: num1 小于 num2"
fi
if [ $num1 -le $num2 ]
then
echo "$num1 -le $num2: num1 小于或等于 num2"
else
echo "$num1 -le $num2: num1 大于 num2"
fi
運行結果為:
num1 為:1
num2 為:2
1 -eq 2: num1 不等于 num2
1 -ne 2: num1 不等于 num2
1 -gt 2: num1 不大于 num2
1 -lt 2: num1 小于 num2
1 -ge 2: num1 小于 num2
1 -le 2: num1 小于或等于 num2
2.3 布爾運算符
布爾運算符也就是我們常說的與或非
運算符 | 說明 | 舉例 |
---|---|---|
-a | 與運算,兩個表達式都為 true 才返回 true。 | [1 -lt 2 -a 10 -gt 2] 返回 true。 |
-o | 或運算,有一個表達式為 true 則返回 true。 | [1 -lt 2 -o 2 -gt 10] 返回 true。 |
! | 非運算,表達式為 true 則返回 false,否則返回 true。 | [! false] 返回 true。 |
例如:
#!/bin/bash
num1=10
num2=20
echo "num1 為: ${num1}"
echo "num2 為: ${num2}"
if [ $num1 -lt 40 -a $num2 -gt 15 ];then
echo "$num1 小于 40 且 $num2 大于 15 : 返回 true"
else
echo "$num1 小于 40 且 $num2 大于 15 : 返回 fnum1lse"
fi
echo "或運算"
if [ $num1 -lt 40 -o $num2 -gt 40 ];then
echo "$num1 小于 40 或 $num2 大于 40 : 返回 true"
else
echo "$num1 小于 40 或 $num2 大于 40 : 返回 fnum1lse"
fi
echo "非運算"
if [ $num1 != $num2 ];then
echo "$num1 != $num2 : num1 不等于 num2"
else
echo "$num1 != $num2: num1 等于 num2"
fi
返回結果為:
num1 為: 10
num2 為: 20
10 小于 40 且 20 大于 15 : 返回 true
或運算
10 小于 40 或 20 大于 40 : 返回 true
非運算
10 != 20 : num1 不等于 num2
[root@master scripts]# vim 2.sh
[root@master scripts]# bash 2.sh
num1 為: 10
num2 為: 20
10 小于 40 且 20 大于 15 : 返回 true
或運算
10 小于 40 或 20 大于 40 : 返回 true
非運算
10 != 20 : num1 不等于 num2
2.4 邏輯運算符
邏輯運算符為,以下介紹 Shell 的邏輯運算符,假定變量 A 為 1,變量 b 為 2:
運算符 | 說明 | 舉例 |
---|---|---|
&& | 邏輯的 AND | [[ $A -lt 10 && $B -gt 100 ]] 返回 false |
|| | 邏輯的 OR | [[ $A -lt 10 || $B -gt 100 ]] 返回 true |
例如:
#!/bin/bash
num1=1
num2=2
echo "num1 為:${num1}"
echo "num2 為:${num2}"
if [[ $num1 -lt 5 && $num2 -gt 5 ]];then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $num1 -lt 5 || $num2 -gt 5 ]];then
echo "返回 true"
else
echo "返回 false"
fi
返回:
num1 為:1
num2 為:2
返回 false
返回 true
2.5 字符串運算符
對于字符串進行一些判斷操作,假定變量 a 為 “l(fā)inux”,變量 b 為 “shell”:
運算符 | 說明 | 舉例 |
---|---|---|
= | 檢測兩個字符串是否相等,相等返回 true。 | [$a = $b] 返回 false。 |
!= | 檢測兩個字符串是否相等,不相等返回 true。 | [$a != $b] 返回 true。 |
-z | 檢測字符串長度是否為 0,為 0 返回 true。 | [-z $a] 返回 false。 |
-n | 檢測字符串長度是否為 0,不為 0 返回 true。 | [-n “$a” ] 返回 true。 |
$ | 檢測字符串是否為空,不為空返回 true。 | [$a] 返回 true。 |
例如:
#!/bin/bash
str1="linux"
str2="shell"
echo "str1 為:${str1}"
echo "str2 為:${str2}"
if [ $str1 = $str2 ];then
echo "$str1 = $str2 : str1 等于 str2"
else
echo "$str1 = $str2: str1 不等于 str2"
fi
if [ $str1 != $str2 ];then
echo "$str1 != $str2 : str1 不等于 str2"
else
echo "$str1 != $str2: str1 等于 str2"
fi
if [ -z $str1 ];then
echo "-z $str1 : 字符串長度為 0"
else
echo "-z $str1 : 字符串長度不為 0"
fi
if [ -n "$str1" ];then
echo "-n $str1 : 字符串長度不為 0"
else
echo "-n $str1 : 字符串長度為 0"
fi
if [ ${str1} ];then
echo "str1 : 字符串不為空"
else
echo "str1 : 字符串為空"
fi
返回為:
str1 為:linux
str2 為:shell
linux = shell: str1 不等于 str2
linux != shell : str1 不等于 str2
-z linux : 字符串長度不為 0
-n linux : 字符串長度不為 0
str1 : 字符串不為空
2.6 文件測試運算符
文件測試在我們編寫 shell 中與文件操作非常常用,熟練掌握文件操作可以在后續(xù)的 shell 編寫中得心應手,例如 file 變量為:
操作符 | 說明 | 舉例 |
---|---|---|
-d | file 檢測文件是否是目錄,如果是,則返回 true。 | [-d $file] 返回 false。 |
-f | file 檢測文件是否是普通文件(既不是目錄,也不是設備文件),如果是,則返回 true。 | [-f $file] 返回 true。 |
-c | file 檢測文件是否是字符設備文件,如果是,則返回 true。 | [-c $file] 返回 false。 |
-b | file 檢測文件是否是塊設備文件,如果是,則返回 true。 | [-b $file] 返回 false。 |
-g | file 檢測文件是否設置了 SGID 位,如果是,則返回 true。 | [-g $file] 返回 false。 |
-u | file 檢測文件是否設置了 SUID 位,如果是,則返回 true。 | [-u $file] 返回 false。 |
-k | file 檢測文件是否設置了粘著位 (Sticky Bit),如果是,則返回 true。 | [-k $file] 返回 false。 |
-p | file 檢測文件是否是有名管道,如果是,則返回 true。 | [-p $file] 返回 false。 |
-r | file 檢測文件是否可讀,如果是,則返回 true。 | [-r $file] 返回 true。 |
-w | file 檢測文件是否可寫,如果是,則返回 true。 | [-w $file] 返回 true。 |
-x | file 檢測文件是否可執(zhí)行,如果是,則返回 true。 | [-x $file] 返回 true。 |
-s | file 檢測文件是否為空(文件大小是否大于 0),不為空返回 true。 | [-s $file] 返回 true。 |
-e | file 檢測文件(包括目錄)是否存在,如果是,則返回 true。 | [-e $file] 返回 true。 |
例如:
#!/bin/bash
TEST_FILE="/etc/fstab"
echo "檢測的文件為:${TEST_FILE}"
echo "文件信息為:$(ls -l ${TEST_FILE})"
if [ -r $TEST_FILE ]
then
echo "文件可讀"
else
echo "文件不可讀"
fi
if [ -w $TEST_FILE ]
then
echo "文件可寫"
else
echo "文件不可寫"
fi
if [ -x $TEST_FILE ]
then
echo "文件可執(zhí)行"
else
echo "文件不可執(zhí)行"
fi
if [ -f $TEST_FILE ]
then
echo "文件為普通文件"
else
echo "文件為特殊文件"
fi
if [ -d $TEST_FILE ]
then
echo "文件是個目錄"
else
echo "文件不是個目錄"
fi
if [ -s $TEST_FILE ]
then
echo "文件不為空"
else
echo "文件為空"
fi
if [ -e $TEST_FILE ]
then
echo "文件存在"
else
echo "文件不存在"
fi
返回為:
檢測的文件為:/etc/fstab
文件信息為:-rw-r--r--. 1 root root 500 Jan 17 14:23 /etc/fstab
文件可讀
文件可寫
文件不可執(zhí)行
文件為普通文件
文件不是個目錄
文件不為空
文件存在
3. 實例
3.1 需求
編寫一個腳本,傳入一個 linux 文件系統(tǒng)的路徑,判斷其下面文件及目錄的數(shù)量。
3.2 思路
可以利用文件測試運算符來判斷輸出的目錄是否正確,之后利用算術運算符配合數(shù)組對文件或目錄進行統(tǒng)計。
3.3 實現(xiàn)
#!/bin/bash
# Description: count file scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# function: count file
# Date: 2020-03-08 14:00
# Version: 1.0
# 判斷輸入?yún)?shù)
[ $# -ne 1 ] && echo "輸入?yún)?shù)錯誤,${0} check_dir" && exit 1
# 判斷輸入的是否為存在的目錄,不存在則退出
CHECK_DIR=$1
[ ! -d ${CHECK_DIR} ] && echo "檢測系統(tǒng)不存在目錄:${CHECK_DIR}, 請輸入正確的目錄" && exit 1
# 對目錄下的文件進行統(tǒng)計
DIR_NUM=0
FILE_NUM=0
OTHER_NUM=0
for item in ${CHECK_DIR}/*
do
if [ -d ${item} ];then
# 如果為目錄,則目錄總數(shù)加一
DIR_NUM=$((${DIR_NUM}+1))
elif [ -f ${item} ];then
FILE_NUM=$((${FILE_NUM}+1))
else
OTHER_NUM=$((${OTHER_NUM}+1))
fi
done
echo "檢測目錄為:${CHECK_DIR}"
echo "文件類型數(shù)量為:${FILE_NUM}"
echo "目錄類型數(shù)量為:${DIR_NUM}"
echo "其他類型數(shù)量為:${OTHER_NUM}"
[root@master scripts]# bash count_file.sh
輸入?yún)?shù)錯誤,count_file.sh check_dir
[root@master scripts]# bash count_file.sh aaaa
檢測系統(tǒng)不存在目錄:aaaa, 請輸入正確的目錄
[root@master scripts]# bash count_file.sh /tmptmptmp
檢測系統(tǒng)不存在目錄:/tmptmptmp, 請輸入正確的目錄
[root@master scripts]# bash count_file.sh /
檢測目錄為:/
文件類型數(shù)量為:0
目錄類型數(shù)量為:23
其他類型數(shù)量為:0
[root@master scripts]# bash count_file.sh /root
檢測目錄為:/root
文件類型數(shù)量為:8
目錄類型數(shù)量為:5
其他類型數(shù)量為:0
[root@master scripts]# bash count_file.sh /dev/
檢測目錄為:/dev/
文件類型數(shù)量為:1
目錄類型數(shù)量為:19
其他類型數(shù)量為:139
當我們不輸入任何參數(shù)的時候,提示需要輸入一個路徑參數(shù),輸入了文件名稱或不存在的路徑時,文件測試運算符判斷輸入異常,不是一個有效的文件目錄。
當我們輸入正常的目錄時,即可獲得正確的目錄或文件數(shù)。
4. 注意事項
- 對于算術運算,大家可以根據(jù)具體場景和環(huán)境來選擇,例如系統(tǒng)內(nèi)沒有計算工具等,可以優(yōu)先選擇
[]
和(())
來進行,也可以根據(jù)自己喜好選擇; - 對于關系運算,比較的數(shù)字,不是字符串,一定要牢記這個注意點,對于字符串判斷可以用字符串運算符;
- 對于布爾運算和邏輯運算其實是一個東西,只不過布爾運算符有一個非運算,可以進行靈活運用;
- 文件測試符常用與判斷 linux 系統(tǒng)文件的操作,在后期 shell 編程可謂舉足輕重,牢記每個文件運算符會使得后期編程得心應手。
5. 小結
運算符可謂 Shell 腳本的靈魂,后期我們的循環(huán)和判斷里面的條件都是這些運算符構成,它是流程框架的基礎,熟練掌握運算符的分類及每個的用法,通過動手實踐區(qū)分其特征,舉一反三靈活運用。