[TOC]

0x03 shell编程运算符

描述:主要是数值命令如declare/let/expr、数值运算方法、变量测试,以及shell变量的弱点默认字符串类型(弱类型)

运算符及优先级:(从高到低)

  • Shell算数运算符
  • 移位运算符
  • 关系(比较)运算符
  • 位运算符
  • 布尔(逻辑)运算符
  • 字符串运算符
  • 赋值运算符

WeiyiGeek.运算符及优先级

1.整数运算

可以进行数值运算的方法有: declare expr le bc [[]] $() awk typeset,下面只是常用的几类;
实际案例:

#!/bin/bash
#示例1.declare命令
a=2
b=8
declare -i c=$a+$b
echo "$a + $b = $c" #2 + 8 = 10


#示例2.let数值运算工具
let test=$a*$b #注意*号左右两侧无格
echo "$a * $b = $test" #2 * 8 = 16
let "test=a + b" #注意在算引号包括的可以存在空格
let value+=2 #c语言方法

let "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 - 4))" # 最后一个表达式变量赋值得给t1(值得学习)
echo "t1 = $t1, a = $a, b = $b, c = $c" #t1 = 11, a = 8, b = 6, c = 11


#示例3.expr命令
cc=$(expr $a \* $b) #注意+号左右两侧必须有空格,乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
echo "$a * $b = $cc" #8 * 6 = 48


#示例4.括号得优先级最大,采用$(())形式计算
a=1;b=2
echo $((a+b)) $(($a+$b)) # 3 3 推荐方式

aa=$(((11+3)*3/2))
bb=$((14%3)) #求余
c

echo "aa = $aa, bb = $bb, cc = $cc" #aa = 21, bb = 2, cc = 8


#示例5.采用$[]形式计算
a=1;b=2
echo $[a+b] $[ $a + $b ] #3 3
cc=$[15+78]; dd=$[15%7]
echo "cc = $cc, dd = $dd" #cc = 93, dd = 1


#示例6.typeset命令
$ typeset -i A=1 B=3
$ A=A+B;echo $A #4


#示例7.自加自减(不带$a)
a=1
let a++ #方式1(不返回值)
echo $a #2
echo $((a++)) #2 #先返回值再加减
echo $[a++] #3
echo $a #4

b=5
let --b #方式2(不返回值)
echo $b #4
echo $((--b)) #3 #先加减再返回值
echo $[--b] #2
echo $b #2

补充示例:

#示例1.从1加到10得表达式计算多种方法
echo "`echo {1..10} | tr " " "+"` = `echo {1..10} | tr " " "+" | bc`"
1+2+3+4+5+6+7+8+9+10 = 55

echo `seq -s '+' 10`=`seq -s '+' 10 | bc`
echo $(seq -s '+' 10)=$(seq -s '+' 10 | bc)
echo "$(seq -s '+' 10)="$(($(seq -s '+' 10)))
1+2+3+4+5+6+7+8+9+10=55

#这里需要注意expr需要在 操作符合两边有空格
echo `seq -s '+' 10`=`seq -s " + " 10|xargs expr`
1+2+3+4+5+6+7+8+9+10=55
#值得学习在正式得使用中很少
echo `seq -s "+" 10`=$(expr $[`seq -s " + " 10`])
1+2+3+4+5+6+7+8+9+10=55


2.浮点数运算

实际案例:

#示例1.精密算术操作高级运算工具:bc计算命令
#可以对于0.00123456789进行计算(前面的都不能进行浮点运算):
echo "1.212*3" | bc
#scale设定小数精度(数值范围),"scale保存的小数位数;表达式"|bc #有效数字
echo "scale=3;4/8"| bc
echo "sqrt(10)" | bc


3.逻辑运算

实际案例:

echo $((1&&0))      #一假必假 0
echo $((1||0)) #一真必真 1
echo $[1&&0] $[1||0] #方式2 0 1

#可以短路求值
echo $(( 1 > 2 && 1 < 2 )) #0
echo $(( 1 > 2 || 1 < 2 )) #1


4.位运算

实际案例:

# 逻辑位移(<< >>)
echo $[3<<2] #3*(2^2) =12
echo $[8>>2] #8/(2^2) =2

#位运算(按位或/与/异或 )
echo $((12|7)) #1100 | 0111 = 1111 = 15
echo $((12&7)) #1100 | 0111 = 0100 = 4
echo $((12^7)) #1100 ^ 0111 = 1011 = 11

注意事项:

  • expr和let不同之处在于乘法需要转义\*,且运算符左右两边必须有空格,而let操作数两边是不能有空格的;
  • 自加自减与其他编程语言是一致的,需要注意是先计算在返回值还是先返回值再计算,不同之处在于let计算时候都是返回计算后的值;

0x04 shell编程数组(Array)

Shell在编程方面比Windows批处理强大很多,无论是在循环、运算,数组作为一种特殊的数据结构在任何一种编程语言中都有它的一席之地,数组在Shell脚本中也是非常重要的组成部分,它借助索引将多个独立的数据存储为一个集合。

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。

bash中的两类数组类型:

  • 普通数组:最常见的数组类型声明格式:array_name=(value0 value1)
  • 关联数组:从bash4.0开始被引入,关联数组的索引值可以使用任意的文本,关联数组在很多操作中很有用;
    • 关联数组的声明(必须声明):declare -A array_var

(1)定义数组
在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。

#定义数组的一般形式为:
array_name=(value0 value1 value2 value3)
array_name=( [0]=one [1]=two [2]=three [3]=four )

#或者:
array_name=(
value0
value1
value2
value3
)
#单独定义数组的各个分量,可以不使用连续的下标,而且下标的范围没有限制。
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
array_name[8]=value8


#关联数组
#使用内嵌索引-值列表法将元素添加到关联数组:
array_var=( [one]=one-1 [two]=two-2 [three]=three-3 [four]=four-4 [five]=five-5 [six]=six-6 )

#使用独立的索引-值进行赋值:
array_var[one]=one-1
array_var[two]=two-2
array_var[three]=three-3
array_var[four]=four-4
array_var[five]=five-5
array_var[six]=six-6


#数组补充使用
array=($(ls)) #将执行的命令放入数组中
for i in ${array[@]};do echo $i;sleep 1; done
~$
Microsoft
Word
文档.docx
Another.Redis.Desktop.Manager.lnk


(2)读取数组并获取信息

  • 读取数组元素值的一般格式是${array_name[index]},可以使用@ (单个参数独立)* (所有参数整体)可以获取数组中的所有元素,利用获取字符串长度的#来获取数组长度的方法与获取字符串长度的方法相同;以及可以对数组进行提取删除等等

实际案例:

array_name=(1 3 5 7 9)
valuen=${array_name[2]}

#示例1.数组读取
NAME[0]="Zara";NAME[1]="Qadir"
echo "First Index: ${NAME[0]}" #Zara
echo "Second Index: ${NAME[1]}" #Qadir


#示例2.获取数组里的所有元素
length=${array_name[*]} # 所有参数 (for循环都差不多)
length=${array_name[@]} # 单个参数独立


#示例3.取得数组元素的个数(数组length)
length=${#array_name[@]} # 或者
length=${#array_name[*]}
length=${#array_name[n]} # 取得数组单个元素的长度


#示例4.数组的提取
array_name=( [0]=one [1]=two [2]=three [3]=four )
${array[@]:0} #显示所有元素
${array[@]:1} #除去第一个元素后的显示所有元素
echo ${array[@]:0:2} #从下标[0]开始依次显示2个数组值 one two
echo ${array[@]:1:2} #从下标[1]开始依次显示2个数组值 two three


#示例5.数组子串替换
echo ${array[@]/o/m} #将o替换成m mne twm three fmur
#如果没有指定替换子串,则删除匹配到的子符
echo ${array[@]//o/} #ne tw three fur
#替换字符串前端(#)子串
echo ${array[@]/#o/k} #kne two three four
#替换字符串后端(%)子串
echo ${array[@]/%o/k} #ne twk three four


#示例5.子串删除、剔除
#左边开始最短的匹配:"t*e",这将匹配到"thre"则显示e
echo ${array[@]#t*e} # 可采用通配符 one two e four
#左边开始最长的匹配,这将匹配到"three",将删除three并输出到屏幕
echo ${array[@]##t*e}

#从字符串的结尾开始最短的匹配o
echo ${array[@]%o} #one tw three four
echo ${array[@]%%o} #one tw three four #从字符串的结尾开始最长的匹配


#示例6.关联数组的使用,关联数组的打印方法跟普通数组用法一样
array_var=( [one]=one-1 [two]=two-2 [three]=three-3 [four]=four-4 [five]=five-5 [six]=six-6 )
#列出数组索引值(值得学习)
echo ${!array_var[*]} #four one five six two three (注意感叹号)

#示例7.采用unset命令删除数组
unset array_pt[0] #删除数组中第一个元素
unset array_pt    #删除整个数组


实战脚本:

#!/usr/bin/env bash
#功能:Shell数组的使用示例
number=(1 2 3)
number[3]=4
string=("I" "Love" "you" "baby" "!")
declare -A relatearray #关联数组的定义(非常重要-A)
relatearray=( [one]=weiyi [two]=geek [there]=computer )

#示例1.输入出数组中各个参数,采用$array[*]与$array[@]都差不多;
echo "#示例1.案例输出"
count=0
for i in ${number[@]};do
flag=$((count++))
echo "number[${flag}] = $i"
done
count=0
for i in ${string[*]};do
flag=$((count++))
echo "string[${flag}] = $i"
done


echo -e "\n#示例2:\n"
#示例2.输出普通以及关联数组的长度以及键值的字符长度
echo "number 数组长度:${#number[*]} , string数组长度:${#string[@]} "
#注意关联数组获取其长度
echo "relatearray关联数组长度:${#relatearray[*]}"

count=0
for i in ${string[*]};do
flag=$((count++))
echo "string[${flag}] 键值 ${string[$flag]} 长度为 ${#string[$flag]}"
done
#关联数组关键点 (先列出数组索引值,然后根据关联索引值输出数组)
for i in ${!relatearray[*]};do
echo "relatearray[${i}] 键值 ${relatearray[${i}]} 长度为 ${#relatearray[${i}]}"
done

echo -e "\n#示例3:\n"
echo "提取数组元素:${number[@]:2} , ${string[*]:3}"
echo "提取从下标[0]开始依次显示2个数组:${number[@]:0:2} , ${string[*]:0:2}"

echo -e "\n#示例4:\n"
#string=("I" "Love" "you" "baby" "!")
#注意这里是 * 而不使用 @
echo "将string数组中o变成大写O:${string[@]/o/O}"
echo "将string数组中o删除:${string[@]//o}"
echo "前匹配替换: ${string[@]/#y/Y} 删除:${string[@]/#y/}"
echo "后匹配替换: ${string[@]/#y/Y} 删除:${string[@]/#y/}"

echo -e "\n#示例5:\n"
echo "左边最短匹配:${string[@]#*o} ,最长匹配:${string[@]##y*u}" #>> 看
echo "右边最短匹配:${string[@]%*o} ,最长匹配:${string[@]%%y*u}" #<< 看


echo -e "\n#示例6:\n"
#示例5.删除数组
unset number[1] number[2]
for i in $(seq 0 3);do
echo "number[${i}] = ${number[$i]}"
done

############### 执行结果 ###########
#示例1.案例输出
number[0] = 1
number[1] = 2
number[2] = 3
number[3] = 4
string[0] = I
string[1] = Love
string[2] = you
string[3] = baby
string[4] = !

#示例2:数组长度
number 数组长度:4 , string数组长度:5
relatearray关联数组长度:3
string[0] 键值 I 长度为 1
string[1] 键值 Love 长度为 4
string[2] 键值 you 长度为 3
string[3] 键值 baby 长度为 4
string[4] 键值 ! 长度为 1
relatearray[one] 键值 weiyi 长度为 5
relatearray[there] 键值 computer 长度为 8
relatearray[two] 键值 geek 长度为 4

#示例3:提取数组
提取数组元素:3 4 , baby !
提取从下标[0]开始依次显示2个数组:1 2 , I Love

#示例4:替换删除
将string数组中o变成大写O:I LOve yOu baby !
将string数组中o删除:I Lve yu baby !
前匹配替换: I Love You baby ! 删除:I Love ou baby !
后匹配替换: I Love You baby ! 删除:I Love ou baby !


#示例5:通配符匹配
左边最短匹配:I ve u baby ! ,最长匹配:I Love baby !
右边最短匹配:I Love you baby ! ,最长匹配:I Love baby !

#示例6:删除数组
number[0] = 1
number[1] =
number[2] =
number[3] = 4


0x05 shell编程变量替换

描述:我们在前面讲解{}作用的时候简单的提出几个变量替换,下面我们进行总结。

  • 变量替换:可以根据变量的状态(是否为空、是否定义等)来变它的值
  • 优点是:效率高、代码精简
  • 缺点是:逻辑难懂

变量置换规则:存在三种情况(变量存在、存在值为空、变量不存在)

${var-value} : 变量var 存在则返回var,否则返回value; 变量var为空值时也返回 空值
${var:-value} : 变量var 存在则返回var,否则返回value; 变量var为空值时返回 value

${var+value} : 变量var 存在则返回value,否则返回为空, 变量var为空值时返回 value
${var:+value} : 变量var 存在则返回value,否则返回为空, 变量var为空值时返回 空值

${var=value} : 变量var 存在返回var(值不变),否则设置var=value并返回value, 变量var 为空时返回空
${var:=value} : 变量var 存在返回var(值不变),否则设置var=value并返回value, 变量var 为空时设置var=value并返回value

${var?value} :变量var 存在返回var,否则将value输出到标准错误输出(stderr), 变量var为空值时也返回 空值
${var?value} :变量var 存在返回var,否则将value输出到标准错误输出(stderr), 变量var将value输出到标准错误输出(stderr)

WeiyiGeek.常用的变量替换

实际案例:

#示例1.{$var-value} 与 {$var:-value}
$ var=1024
$ echo ${var-512} "|" $var #1024 | 1024
$ echo ${var:-512} "|" $var #1024 | 1024
##后者与前者不同在于变量$var是否为空
$ var=
$ echo ${var-512} "|" $var # 空值 | 空值 (对比点)
$ echo ${var:-512} "|" $var # 512 | (对比点)
$ unset $var
$ echo ${var-512} "|" $var # 512 |
$ echo ${var:-512} "|" $var # 512 |



#示例2.{$var+value} 与 {$var:+value} 与上面相反在y设置值时候才返回valur
$ var=512
$ echo ${var+1024} "|" $var #1024 | 512
$ echo ${var:+1024} "|" $var #1024 | 512
$ var=
$ echo ${var+1024} "|" $var #1024 |
$ echo ${var:+1024} "|" $var # |
$ unset var
$ echo ${var+1024} "|" $var # |
$ echo ${var:+1024} "|" $var # |


#示例3.${var=value} 和 ${var:=value}
$ var=512
$ echo ${var=1024} "|" $var
512 | 512
$ echo ${var:=1024} "|" $var
512 | 512

$ var=
$ echo ${var=1024} "|" $var # | #不同点
$ echo ${var:=1024} "|" $var # 1024 | 1024

$ unset var
$ echo ${var=1024} "|" $var
1024 | 1024
$ echo ${var:=1024} "|" $var
1024 | 1024


#示例4.${var?value} 和 ${var:?value}
$ var=1024
$ echo ${var?512} "|" $var
1024 | 1024
$ echo ${var?=512} "|" $var
1024 | 1024

$ var=
$ echo ${var?512} "|" $var # | #对比点
$ echo ${var:?512} "|" $var #bash: var: 512

$ unset var
$ echo ${var?512} "|" $var #bash: var: 512
$ echo ${var:?512} "|" $var #bash: var: 512

实际案例2:

#!/bin/bash
#变量替换测试代码
var=1024
echo "1 - Value of var is ${var}" ${var:-"Variable is not set"} # 1 - Value of var is 1024 1024
echo "2 - Value of var is ${var}" ${var:+"Variable is not set"} # 2 - Value of var is 1024 Variable is not set
echo "3 - Value of var is ${var}" ${var:="Variable is not set"} # 2 - Value of var is 1024 1024
echo "4 - Value of var is ${var}" ${var:?"Variable is not set"} # 2 - Value of var is 1024 1024

echo "1 - Value of var is $var" ${var-"This is default value"} # 1 - Value of var is 1024 1024
echo "2 - Value of var is $var" ${var+"This is default value"} # 2 - Value of var is 1024 This is default value
echo "3 - Value of var is $var" ${var?"This is default value"} # 2 - Value of var is 1024 1024
echo "4 - Value of var is $var" ${var="This is default value"} # 4 - Value of var is 1024 1024

unset var
#4 - Value of var is 1024 This is default value
echo "4 - Value of var is $var" ${var:+"This is default value"} #var未定义,将不会返回word的至
#5 - Value of var is 1024 1024
echo "5 - Value of var is ${var}" ${var:?"Print this message"}


0x06 shell编程变量测试

描述:变量测试时shell编程中最重要的一个环节,可以更据条件进行执行相应的代码;Shell中的 test 命令 或者 [[ ]] 用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

虽然test与[]也能达到效果,但还是建议采用[[]]来进行变量测试,同test命令为真返回0,否则返回非0
变量测试方式:只对shell有效,在脚本优化时候使用,推测y的值来给x赋值

变量测试说明:

# 按文件类型进行判断
-e 该『文件名』是否存在?(常用)
-f 该『文件名』是否为文件(file)?(常用)
-d 该『文件名』是否为目录(directory)?(常用)
-b 该『文件名』是否为一个 block device 装置?
-c 该『文件名』是否为一个 character device 装置?
-p 该『文件名』是否为一个 FIFO 管道(pipe) 文件?
-L 该『文件名』是否为一个符号链接文件?
-s 该『文件』大小是否不为 0如果大于0为真否则为假;
-S 该『文件名』是否为一个 Socket (套接字) 文件?

# 按文件权限进行判断
-r 侦测该文件名是否具有『可读』的属性?
-w 侦测该文件名是否具有『可写』的属性?
-x 侦测该文件名是否具有『可执行』的属性?
-u 侦测该文件名是否具有『SUID』的属性?
-g 侦测该文件名是否具有『SGID』的属性?
-k 侦测该文件名是否具有『Sticky bit』的属性?


# 两个文件之间的比较
-nt (newer than)判断 file1 是否比 file2 新 (New)
-ot (older than)判断 file1 是否比 file2 旧 (Old)
-ef 判断 file2 与 file2 是否为同一文件,可用在判断 hard link 的判定上 #主要意义在判定,两个文件是否均指向同一个 inode 号!


# 表达式的逻辑体条件(注意与其他编程语言有所不同,两个都为真0采返回0,否则返回1)
# [] 可采用前者-a,[[]]可采用后者 &&
-a 或 && :逻辑与,“而且”的意思,前后两个表达式都成立时整个测试结果才为真,否则为假
-o 或 || : 逻辑或,“或者”的意思,操作符两边至少一个为真时,结果为真,否为为假
! :逻辑否,当制定条件不成立时,返回结果为真


# 判断字符串
[ 字符串1 = 字符串2] # 可以使用 " == " 代替
[ 字符串1 != 字符串2] # 可以使用 " !== " 代替
[ –n 字符串 ] #字符串的长度非零
[ –z 字符串 ] #字符串的长度是否为零
[ string1 \< string2 ] #如果string1在本地的字典序列中排在string2之前,则为真
[ string1 \> string2 ] #如果string1在本地的字典序列中排在string2之后,则为真


#判断整数 ,在[[]] 可以使用替换字符 (0~9可以,但是超出后建议使用 -nn 形式比较)
#建议采用 (()) 两个形式都通用
-eq:等于(equal) # 可采用 == 或 = 替代
-ne:不等于(not equal) # 可采用 != 替代
-gt:大于(Greater than) # 可采用 > 替达
-lt:小于(lesser than) # 可采用 < 替达
-le:小于等于(lesser or equal) # 可采用 <= 替达 [[]] 不能使用
-ge:大于等于(Greater or equal) # 可采用 >= 替达 (()) 不能使用

#也可以采用转义 大于与小于 来实现整数对比,由于和重定向符号冲突
[ 2 \> 1] #而且单[]需要转义 也不能采用 <= 与 >=
[[ 1 < 2]] #双[[]]不需要转义 不建议采用
#[[ 1 <= 2]] #双[[]]/[]不能采用才中形式会报错
((1<2)) #无需空格间隔
((1>=2))

简单案例:

#示例1.判断目录与文件类型,真则输出yes否则返回no , 三种方法test [] [[]]
test -f ww.php && echo 1 || echo 0 #1
test -d ww.php && echo 1 || echo 0 #0
[ -d ~/.ssh/ -a -f ~/.bashrc ] && echo "yes" || echo "no" $yes
[[ -f ww.php ]] && echo 1 || echo 0 #1


#示例2.判断变量aa是否有值,同时判断值是否大于23
aa=11
[ -n $aa -a $aa -gt 123 ] && echo "yes" || echo "no" #no [] 采用形式
[[ -n $aa && $aa -gt 123 ]] && echo "yes" || echo "no" #no [[]] 采用形式
#如果[]先采用&&符号怎么办?分割比较表达式即可
[ -n "$aa" ] && [ $aa -gt 123] && echo "yes" || echo "no" #no 效果同上


#示例3.判断是空串吗? -z 与-n功能相反
echo -e "\e[1;34m #变量测试:短路求值的功效(与C语言的&& || 隐性规则一致) \e[0m"
[[ -z "111" ]] && echo "w" || echo "whoami"
[[ -z "" ]] && echo "w" || echo "whoami"
[[ -z "1" ]] && echo "is null" || echo "is not null" #is not null
[[ -z "" ]] && echo "is null" || echo "is not null" #is null
[ "web" \< "weba" ] && echo 1 || echo 0 # 1 字符比较是按照字母顺序比较的注意转义
[[ "web" < "aweba" ]] && echo 1 || echo 0 # 0 #不需要转义


#示例4.str检测字符串是否为空,不为空返回 true。
read a
if [ $a ];then
echo "$a : string is not empty"
else
echo "$a : string is empty"
fi
#abc : string is not empty


#示例5.判断软硬链接
[ /root/student.txt -ef /tmp/su.txt ] && echo "true" || echo "false" #false
#[[]] 必须有空格 = test
#是否是文件,文件是否存在
$[[ -f 1.txt ]]&& echo "1.txt is file" || echo "1.txt is notfile"
1.txt is file

#是否是可执行文件
[[ -x 1.txt ]]&& echo "1.txt can be execute" || echo "1.txt can't be execute"
#1.txt can't be execute
$chmod +x 1.txt
[[ -x 1.txt ]]&& echo "1.txt can be execute" || echo "1.txt can be execute"
#1.txt can be execute

#是否是目录
$[[ -d 1.txt ]] && echo "1.txt is dir" || echo "1.txt is't dir"
#1.txt is't dir
$[[ -d /bin ]] && echo "1.txt is dir" || echo "1.txt is't dir"
#1.txt is dir


##########*补充知识点:*#################
#注意在root用户下所有的文件是可读的,即便是000权限
[email protected]:~$ ll www.txt
---------- 1 ubuntu ubuntu 0 Jul 12 12:25 www.txt
$root@WeiyiGeek:/home/ubuntu# [[ -r www.txt ]] && { #代码块形式值值得学习,可以替换if .. then ...语句
echo 1
echo 2
echo 3
}
1
2
3

#示例1.补充示例从标准输入输出
[ $1 -eq 3 ] && { echo 1;echo 2;echo 3 }


#示例2.表达式空格影响(一定要在表达式中使用双引号包含变量)
[email protected]:/home/ubuntu# [ "abc" == "1" ] && echo "相等" || echo "不相等" #分割字符串比较
#不相等
[email protected]:/home/ubuntu# [ "abc"=="1" ] && echo "相等" || echo "不相等" #
#相等


#示例3.采用转义后的大于小于来实现,而双[[]]不需要转义
$ [ 2 \< 1 ] && echo 1 || echo 0 #0 需要转义 ,并且注意空格和比较符合的间隔
$ [ 2 \> 11 ] && echo 1 || echo 0 #1 注意的是只比较第一位数值;比较(0~9)可以采用
$ [[ 2 > 1 ]] && echo 1 || echo 0 #1 不需要转义
$ [[ 2 > 11 ]] && echo 1 || echo 0 #1 注意的是只比较第一位数值;比较(0~9) 可以采用

$ (( 1 <= 2 )) && echo 1 || echo 0 #1 不需要转义
$ (( 1 >= 2 )) && echo 1 || echo 0 #0 不需要转义
$ (( 2 < 11 )) && echo 1 || echo 0 #1 不会存在[[]]只比较第一个字符,任意数值都能使用
$ ((2>11)) && echo 1 || echo 0 #0 不需要转义,并且注意无需空格和常规数学比较符号

#!/bin/bash
#下面这种Shell写法常常会在linux中看见,特别是命令执行的时候
clear

cat <<DOC
# 这里是菜单提示 #
#Step1.判断变量值是否存在
#Step2.校验变量值类型
#step3.进行传入变量值进行下一步操作
DOC

read -p "请输入两个数值(如:1 2):" num1 num2
#注意空格
[ -z "$num1" -a -z "$num2" ] && {
echo "[*] input Error ";exit 1
}

#注意采用""和''包含表达式
[ '`echo "$num1" | sed -r "s#[^0-9]##g"`"' == "$num1" ] && {
echo "输入的第一个值非数值"
exit 0
}

[ '`echo "$num2" | sed -r "s#[^0-9]##g"`' == "$num2" ] && {
echo "输入的第一个值非数值"
exit 0
}

#比较判断两个数值
(("$num1">"$num2")) && {
echo " $num1 > $num2 "
}
(("$num1"<"$num2")) && {
echo " $num1 < $num2 "
}
(("$num1"=="$num2")) && {
echo " $num1 == $num2 "
}

注意事项:

  • shell编程中下面的脚本命令后面不用加”;”
  • 在使用[ ]进行变量测试的时候,表达式离两边 [ ] / [[]] 有空格(十分注意);
  • 在使用(())进行变量测试的时候,表达式离两边 () 无需空格(十分注意);
  • [ -d "$wh" ]测试都需要将变量使用 "" 包含然后再比较,注意在进行整数比较时候无需采用
  • 在采用[]进行整型比较时候(不建议采用””包含整数)必须对 “>” 和 “<”进行转义才能达到正确的结果,而使用[[]]和(())时候可以不用转义
  • 在[[]]采用大于小于时候结果可能不对,只比较了第一位;所以在比较时候优先采用 -lt 形式 或者 (($1>$2))
  • 在test与[]可采用-a形式,在[[]]中可采用&&形式,多个 [] 之间以及多个 [[]] 之间可以采用混合逻辑符号 && 或 ||;