shell 比较运算符一览表

运算符 描述 示例
文件比较运算符 
-e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ]
-s filename 如果 filename 存在且不为空,则为真 [ -s /var/log/syslog ]
-d filename 如果 filename 为目录,则为真 [ -d /tmp/mydir ]
-f filename 如果 filename 为常规文件,则为真 [ -f /usr/bin/grep ]
-L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
-w filename 如果 filename 可写,则为真 [ -w /var/mytmp.txt ]
-x filename 如果 filename 可执行,则为真 [ -L /usr/bin/grep ]
filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string 如果 string 长度为零,则为真 [ -z "$myvar" ]
-n string 如果 string 长度非零,则为真 [ -n "$myvar" ]
string1 = string2 如果 string1 与 string2 相同,则为真 [ "$myvar" = "one two three" ]
string1 != string2 如果 string1 与 string2 不同,则为真 [ "$myvar" != "one two three" ]
算术比较运算符
num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]

 

算术运算符 

+ - * / % 表示加、减、乘、除、取余运算

+=、 -=、 *=、 /= 同 C 语言中的含义

 

位操作符

> >>= 表示位左右移一位操作

& &= | |= 表示按位与、位或操作

~ ! 表示非操作

^ ^= 表示异或操作 

 

关系运算符 

= == != 表示大于、小于、大于等于、小于等于、等于、不等于操作

&& || 逻辑与、逻辑或操作

 

测试命令

test命令用于检查某个条件是否成立,它可以进行数值、字符和文件3个方面的测试,其测试符和相应的功能分别如下

(1)数值测试:

  -eq 等于则为真。

  -ne 不等于则为真。

  -gt 大于则为真。

  -ge 大于等于则为真。

  -lt 小于则为真。

  -le 小于等于则为真。

(2)字串测试:

  = 等于则为真。

  != 不相等则为真。

  -z字串 字串长度伪则为真。

  -n字串 字串长度不伪则为真。

(3)文件测试:

  -e文件名 如果文件存在则为真。

  -r文件名 如果文件存在且可读则为真。

  -w文件名 如果文件存在且可写则为真。

  -x文件名 如果文件存在且可执行则为真。

  -s文件名 如果文件存在且至少有一个字符则为真

  -d文件名 如果文件存在且为目录则为真。

  -f文件名 如果文件存在且为普通文件则为真。

  -c文件名 如果文件存在且为字符型特殊文件则为真。

  -b文件名 如果文件存在且为块特殊文件则为真

条件变量替换: 

Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换,替换条件放在{}中. 

(1) ${value:-word} 

当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值. 

(2) ${value:=word} 

与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将 word赋值给value 

(3) ${value:?message} 

若变量已赋值的话,正常替换.否则将消息message送到标准错误输出(若此替换出现在Shell程序中,那么该程序将终止运行) 

(4) ${value:+word} 

若变量赋值的话,其值才用word替换,否则不进行任何替换 

(5) ${value:offset} 

${value:offset:length} 从变量中提取子串,这里offset和length可以是算术表达式. 

(6) ${#value} 

变量的字符个数 

(7) ${value#pattern} 

       ${value##pattern} 

       去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配 

       #与##的区别在于一个是最短匹配模式,一个是最长匹配模式. 

(8) ${value%pattern} 

       ${value%%pattern} 

       于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样 

(9) ${value/pattern/string} 

       ${value//pattern/string} 

       进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区别与上同 

注意:上述条件变量替换中,除(2)外,其余均不影响变量本身的值 

#!/bin/bash

var1="1"
var2="2"

下面是“”运算符-a,另外注意,用一个test命令就可以了,还有if条件后面的分号

if test $var1 = "1"-a $var2 = "2" ; then
   echo "equal"
fi

下面是“”运算符 -o,有一个为真就可以

if test $var1 != "1" -o $var2 != "3" ; then
   echo "not equal"
fi

 

完整示例:

#!/bin/bash

var1="1"
var2="2"
var3="3"

if test $var1 = "1" -o $var2 = "2"; then
    echo "equal"
else
    echo "no equal"
fi

if test $var1 = "1" -o $var2 = $var3; then
    echo "no equal"
fi

运行结果:

equal

no equal

 

“非”运算符 !

if条件是为真的时候执行,如果使用!运算符,那么原表达式必须为false

if ! test $var1 != "1"; then
   echo "not 1"
fi

以上三个if都为真,所以三个echo都会打印

示例:

#!/bin/sh

aa="August 15, 2012"
bb="August 15, 20122"
cc="123"
dd="123"

# -o
if [ "$aa" = "$bb" -o "$cc" = "$dd" ]; then
	echo "yes"
else
	echo "no"
fi

# -a and !
if [ "$aa" != "$bb" -a "$cc" = "$dd" ]; then
	echo "yes"
else
	echo "no"
fi

运行结果:

true

 

shell字符串比较、判断是否为数字

二元比较操作符,比较字符串或者比较数字,注意数字与字符串的区别.

1、 整数比较

-eq       等于,如:if [ "$a" -eq "$b" ]

-ne       不等于,如:if [ "$a" -ne "$b" ]

-gt       大于,如:if [ "$a" -gt "$b" ]

-ge       大于等于,如:if [ "$a" -ge "$b" ]

-lt       小于,如:if [ "$a" -lt "$b" ]

-le       小于等于,如:if [ "$a" -le "$b" ]

<       小于(需要双括号),如:(("$a" < "$b"))

<=       小于等于(需要双括号),如:(("$a" <= "$b"))

>       大于(需要双括号),如:(("$a" > "$b"))

>=       大于等于(需要双括号),如:(("$a" >= "$b"))

整数比较实例

#!/bin/bash


file='folder_url_top24/url_usa_top24_0'
fileSize=`ls -l folder_url_top24/url_usa_top24_0 | awk -F '[" "]' '{print $5}'`
FILESIZE=1000
#while [ ! -f $file -o "$fileSize" -lt "$FILESIZE" ]
#while [ ! -f $file -o "$fileSize" -lt 1000 ]
while (("$fileSize" < 1000)) 
do
    echo "down again..."
done

其中,下面三种整数比较都成立:

1) while [ ! -f $file -o "$fileSize" -lt "$FILESIZE" ]

2) while [ ! -f $file -o "$fileSize" -lt 1000 ]

3) (("$fileSize" < 1000))

推荐使用第一种

 

2、 浮点数比较

shell(bash) 本身没有小数、浮点数计算,但可以借助 bc 命令(高精度的计算器工具)实现浮点数计算,也可以利用awk进行浮点数计算

bc – An arbitrary precision calculator language

例如,我们要计算linux服务器的负载情况,获取5分钟平均负载情况,大于5则杀死一些进程

1)top 查看负载

# top -b | head -n1

top - 13:14:54 up 47 days, 18:40,  1 user,  load average: 1.32, 0.81, 0.05

 

2) awk 获取5分钟平均负载

# top -b | head -n1 | awk '{print $12}' | cut -d ',' -f1

1.32

解释命令:

a) top -b 获取文本格式,否则会报错  shell illegal character: ^[

b)awk '{print $12}'  获取第12个字段(起始下标为1),即5分钟平均负载值

c) cut -d ',' -f1   分割5分钟平均负载值(1.32,)注意:第12个字段有一个逗号

 

3)bc 计算浮点数

常量示例:

if [ `echo "1.1 > 1" | bc` -eq 1 ];then
    echo "OK"
fi

 

变量示例:

load_average_num=`top -b | head -n1 | awk '{print $12}' | cut -d ',' -f1`
load_average_MaxNUM=5
if [ $(echo "$load_average_num > $load_average_MaxNUM"|bc) -eq 1 ]; then
    echo "kill python..." >> $log
    ps -ef | grep -v grep | grep 'python' | awk '{print $2}' | xargs kill -9
    ps -ef | grep -v grep | grep 'main.py' | awk '{print $2}' | xargs kill -9
fi

 

实际应用的完整示例:

######  monitor load average  by  mimvp.com  ######
load_average_num=`top -b | head -n1 | awk '{print $12}' | cut -d ',' -f1`
load_average_MaxNUM=5
echo "load_average_num: $load_average_num"
echo "load_average_num: $load_average_num" >> $log

#while [ `echo "1.1 > 1" | bc` -eq 1 ]; do
#while [ `echo "$load_average_num > $load_average_MaxNUM" | bc` -eq 1 ]; do
while [ $(echo "$load_average_num > $load_average_MaxNUM"|bc) -eq 1 ]; do
    echo "load_average_num: $load_average_num > load_average_MaxNUM: $load_average_MaxNUM" >> $log
    echo "kill python, firefox..." >> $log

    ps -ef | grep -v grep | grep 'python' | awk '{print $2}' | xargs kill -9
    ps -ef | grep -v grep | grep 'main.py' | awk '{print $2}' | xargs kill -9
    ps -ef | grep -v grep | grep 'firefox' | awk '{print $2}' | xargs kill -9
    ps -ef | grep -v grep | grep 'Xvfb' | awk '{print $2}' | xargs kill -9
    sleep 10

    load_average_num=`top -b | head -n1 | awk '{print $12}' | cut -d ',' -f1`
    echo "restart load_average_num: $load_average_num" >> $log
done

 

3、 字符串比较

=       等于,如:if [ "$a" = "$b" ]

==       等于,如:if [ "$a" == "$b" ],与=等价

注意:==的功能在[[]]和[]中的行为是不同的,如下:

1 [[ $a == z* ]]    # 如果$a以"z"开头(模式匹配)那么将为true

2 [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么结果为true

3

4 [ $a == z* ]      # File globbing 和word splitting将会发生

5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true

一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是.

但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像.

!=  不等于,如:if [ "$a" != "$b" ]

这个操作符将在[[]]结构中使用模式匹配.

< 小于,在ASCII字母顺序下.如:

if [[ "$a" < "$b" ]]

 

if [ "$a" \< "$b" ]

 

注意:在[]结构中"<"需要被转义.

> 大于,在ASCII字母顺序下.如:

if [[ "$a" > "$b" ]]

if [ "$a" \> "$b" ]

注意:在[]结构中">"需要被转义.

具体参考Example 26-11来查看这个操作符应用的例子.

-z  字符串为"null".就是长度为0

-n  字符串不为"null"

 

判断shell传入的参数个数是否为空:

#!/bin/bash

port=6379		# 命令行没参数,默认指定端口号为 6379
if [ $# -ge 1 ]; then	# 命令行参数个数大于等于1,则使用传入的参数port
	port=$1		# 获取指定端口号
fi
	
echo "redis port: $port"
redis-cli -h 172.1628.10.114 -p $port

 

字符串比较实例:

if [ "$var1" = "$var2" ]

代码:

#!/bin/sh

aa="August 15, 2012"
bb="August 15, 2012"

if [ "$aa" = "$bb" ]; then
	echo "yes"
else
	echo "no"
fi

判断子字符串包含关系: =~

代码:

a1="ithomer"
a2="ithomer.net"
a3="blog.ithomer.net"

if [[ "$a3" =~ "$a1" ]]; then
         echo "$a1是$a3的子串!"
else
         echo "$a1不是$a3的子串!"
fi

if [[ "$a3" =~ "$a2" ]];then
         echo "$a2是$a3的子串!"
else
         echo "$a2不是$a3的子串!"
fi

 

注意:

使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z或者就是未用""引用的字符串本身,放到[]结构中。

虽然一般情况下可以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯.

awk '{print $2}' class.txt | grep '^[0-9.]' > res

 

 

shell 中 if 做比较

1、shell判断数组中是否包含某个元素

ary=(1 2 3)
a=2
if [[ "${ary[@]}" =~ "$a" ]] ; then
    echo "a in ary"
else
    echo "a not in ary"
fi

 

2、判读字符串($str)是否包含另一个字符串($str1)

方法1:

if [  `echo $str | grep -e '$str1'`  ] ; then
    echo yes
fi

方法2:

如果$str1在判断中直接使用字符串而不是变量,则不能加引号,如if [[ $str =~ ^dx ]]判读字符串$str是否以dx开头,^dx不能加引号:

if [[ $str =~ $str1 ]] ; then
    echo yes
fi

 

3、比较两个字符串是否相等的办法是:

if [ "$test"x = "test"x ]; then

这里的关键有几点:

1)使用单个等号

2)注意到等号两边各有一个空格:这是unix shell的要求

3)注意到"$test"x最后的x,这是特意安排的,因为当$test为空的时候,上面的表达式就变成了x = testx,显然是不相等的。而如果没有这个x,表达式就会报错:[: =: unary operator expected

 

二元比较操作符,比较变量或者比较数字,注意数字与字符串的区别.

整数比较

-eq 等于,如:if [ "$a" -eq "$b" ]

-ne 不等于,如:if [ "$a" -ne "$b" ]

-gt 大于,如:if [ "$a" -gt "$b" ]

-ge 大于等于,如:if [ "$a" -ge "$b" ]

-lt 小于,如:if [ "$a" -lt "$b" ]

-le 小于等于,如:if [ "$a" -le "$b" ]

大于(需要双括号),如:(("$a" > "$b"))

>= 大于等于(需要双括号),如:(("$a" >= "$b"))

小数据比较可使用AWK

 

字符串比较

= 等于,如:if [ "$a" = "$b" ]

== 等于,如:if [ "$a" == "$b" ],与=等价

注意:==的功能在[[]]和[]中的行为是不同的,如下:

1 [[ $a == z* ]] # 如果$a以"z"开头(模式匹配)那么将为true

2 [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么结果为true

3

4 [ $a == z* ] # File globbing 和word splitting将会发生

5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true

一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是.

但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像.

!= 不等于,如:if [ "$a" != "$b" ]

这个操作符将在[[]]结构中使用模式匹配.

大于,在ASCII字母顺序下.如:

if [[ "$a" > "$b" ]]

if [ "$a" \> "$b" ]

注意:在[]结构中">"需要被转义.

具体参考Example 26-11来查看这个操作符应用的例子.

-z 字符串为"null".就是长度为0.

-n 字符串不为"null"

 注意:

使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z

或者就是未用""引用的字符串本身,放到[]结构中。虽然一般情况下可

以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯.

 

if 判断式

if [ 条件判断一 ] && (||) [ 条件判断二 ]; then

elif [ 条件判断三 ] && (||) [ 条件判断四 ]; then

else

   执行第三段內容程式

fi

 

示例1:

flag=0
webip=''
retry_NUM=3
retry_idx=0

while [ "$flag" -gt "0" -a "$retry_idx" -lt "$retry_NUM" ] || [ -z "$webip" -a "$retry_idx" -lt "$retry_NUM" ]
do
    retry_idx=`expr $retry_idx + 1`
    sleep $retry_idx

    echo "flag: $flag , webip: $webip , retry_NUM: $retry_NUM , retry_idx: $retry_idx  "
done

运行结果:

flag: 0 , webip:  , retry_NUM: 3 , retry_idx: 1 
flag: 0 , webip:  , retry_NUM: 3 , retry_idx: 2 
flag: 0 , webip:  , retry_NUM: 3 , retry_idx: 3 

 

示例2:

# a=0
# b=0
# c=5         
# if [ $a = 0 -a $b = 0 ]&&[ $c != 0 ]; then
> echo success
> fi
success

 

if 使用的表达式

Primary 意义

[ -a 文件 ] 如果文件存在为真。

[ -b 文件 ] 如果 文件 存在 而且 是一个 块-特殊 文件为真。

[ -c 文件 ] 为真 如果 文件 存在 而且 是一个 字-特殊 文件。

[ -d 文件 ] 为真 如果 文件 存在 而且 是一个 目录。

[ -e 文件 ] 为真 如果 文件 存在。

[ -f 文件 ] 为真 如果 文件 存在 而且 是一个 普通 文件。

[ -g 文件 ] 为真 如果 文件 存在 而且 已经设置了他的 SGID 位。

[ -h 文件 ] 为真 如果 文件 存在 而且 是一个 符号连接。

[ -k 文件 ] 为真 如果 文件 存在 而且 他的粘住位已经设置。

[ -p 文件 ] 为真 如果 文件 存在 而且 是一个 已经命名的管道 (F 如果O)。

[ -r 文件 ] 为真 如果 文件 存在 而且 是可读的。

[ -s 文件 ] 为真 如果 文件 存在 而且 比零字节大。

[ -t FD ] 为真 如果 文件 文件描述符已经打开 而且 指向一个终端。

[ -u 文件 ] 为真 如果 文件 存在 而且 已经设置了他的 SUID (set user ID)位。

[ -w 文件 ] 为真 如果 文件 为真 如果 文件 存在 而且 是可写的。

[ -x 文件 ] 为真 如果 文件 存在 而且 是可执行的。

[ -O 文件 ] 为真 如果 文件 存在 而且 属于有效用户ID。

[ -G 文件 ] 为真 如果 文件 存在 而且 属于有效组ID。

[ -L 文件 ] 为真 如果 文件 存在 而且 是一个 符号连接。

[ -N 文件 ] 为真 如果 文件 存在 而且 has been mod 如果ied since it was last read。

[ -S 文件 ] 为真 如果 文件 存在 而且 是一个 socket。

[ 文件1 -nt 文件2 ] 为真 如果 文件1 has been changed more recently than 文件2, or 如果

文件1 存在 而且

文件2 does not。

[ 文件1 -ot 文件2 ] 为真 如果 文件1 比 文件2 旧, 或者 文件2 存在而且 文件1 不存在。

[ 文件1 -ef 文件2 ] 为真 如果 文件1 而且 文件2 refer to the same device 而且 inode

numbers。

[ -o 选项名 ] 为真 如果 shell 选项 "选项名" 开启。

[ -z STRING ] 为真 如果 "STRING"的长度是零。

[ -n STRING ] 或者 [ STRING ] 为真 "STRING"的长度是非零值。

[ STRING1 == STRING2 ] 如果两个字符串相等为真。 "=" may be used instead of "==" for

strict POSIX compliance。

[ STRING1 != STRING2 ] 为真 如果 两两个字符串不相等。

[ STRING1 < STRING2 ] 为真 如果 "STRING1" sorts before "STRING2" lexicographically in the

 

current locale。

[ STRING1 > STRING2 ] 为真 如果 "STRING1" sorts after "STRING2" lexicographically in the

current locale。

[ ARG1 OP ARG2 ]

"OP" 是 -eq, -ne, -lt, -le, -gt or -ge 其中一个。 These arithmetic binary operators

return 为真 如果 "ARG1" is equal to, not equal to, less than, less than or equal to, greater

than, or greater than or equal to "ARG2", respectively。 "ARG1" 而且 "ARG2" are

integers。

表达式可以借以下操作符组合起来, listed in decreasing order of precedence:

操作符效果

[ ! EXPR ] 如果EXPR 为假则为真。

[ ( EXPR ) ] 返回EXPR 的值。 这样可以用来忽略正常的操作符优先级。

[ 表达式1 -a 表达式2 ] 如果表达式1 而且表达式2 同时为真则为真 。

[ 表达式1 -o 表达式2 ] 如果表达式1 或者表达式2 其中之一为真则为真。

 

shell 中变量间接引用:

假设a=b,b=123,如何通过a获得123呢,通过变量间接引用可以做到:eval a=\$$b (bash版本2中a=${!b}也可以做到)

 

 

推荐参考:

Linux Shell 函数返回值

Linux 之 shell 算术运算符

Linux shell 脚本通过expect实现自动输入密码