上回梳理 了Linux Shell编程中 () 、$()和 (())的用法,现在接着梳理 [] 和[[]]的用法。
[和test等同,是 Shell 内置命令,用来检测某个条件是否成立。条件成立时退出状态为 0,否则为非 0 值。
Test和[]中,可用的比较运算符只有 ==(或=) 和 !=,两者都是用于字符串比较的,不可用于整数比较。
实例:
我们先定义字符串s1="abc"和s2="def"
然后在[]中分别使用==和!=来在bash和zsh进行测试。
1.在bash中
[csdn ~]$ s1="abc"; s2="def"
[csdn ~]$ echo $[ $s1 != $s2 ]
0
[csdn ~]$ if [ $s1 != $s2 ] ; then echo s1=$s1; else echo s2=$s2; fi
s1=abc
[csdn ~]$ echo $[ $s1 == $s2 ]
1
[csdn ~]$ if [ $s1 == $s2 ] ; then echo s1=$s1; else echo s2=$s2; fi
s2=def
[csdn ~]$ echo $[ s1 == s2 ]
1
[csdn ~]$
2.在zsh中
csdn @ edu $ s1="abc"
csdn @ edu $ s1="abc";s2="def"
csdn @ edu $ echo $[ $s1 != $s2 ]
0
csdn @ edu $ if [ $s1 != $s2 ] ; then echo s1=$s1; else echo s2=$s2; fi
else>
csdn @ edu $ echo $[ $s1 == $s2 ]
1
csdn @ edu $ if [ $s1 == $s2 ] ; then echo s1=$s1; else echo s2=$s2; fi
else>
csdn @ edu $ echo $[ s1 == s2 ]
1
csdn @ edu $
对字符串比较,是否直接可用使用大于号(>)和小于号(<)呢?
1.在bash中
[csdn ~]$ s1="abc"
[csdn ~]$ s2="def"
[csdn ~]$ echo $[ $s1 > $s2 ]
0
[csdn ~]$ [ $s1 \> $s2 ]
[csdn ~]$ echo $?
1
[csdn ~]$ echo $[ $s1 < $s2 ]
0
[csdn ~]$ [ $s1 \< $s2 ]
[csdn ~]$ echo $?
0
[csdn ~]$
在上面的例子中,我们先定义了字符串变量s1="abc"和 s2="def",然后在[]中直接使用 > 和 < 对s1和s2进行比较,显示结果都是1,明显有问题。
当我们在[]中使用 \> 和 \< 来对s1和s2进行比较,结果分别是1和0,这才是正确的结果。
可见,在bash中,对于字符串比较,可以使用转义形式用大于号(>)和小于号(<)。
2.在zsh中
user # csdn zsh $ s1="abc"
user # csdn zsh $ s2="def"
user # csdn zsh $ echo $[ $s1 > $s2 ]
0
user # csdn zsh $ [ $s1 \> $s2 ]
zsh: condition expected: >
user # csdn zsh $ echo $?
1
user # csdn zsh $ echo $[ $s1 < $s2 ]
0
user # csdn zsh $ [ $s1 \< $s2 ]
zsh: condition expected: <
user # csdn zsh $ echo $?
1
在上面的例子中,我们同样先定义了字符串变量s1="abc"和 s2="def",然后在[]中直接使用 > 和 < 对s1和s2进行比较,显示结果都是0,与bash中不同,但同样明显有问题。
当我们在[]中使用 \> 和 \< 来对s1和s2进行比较,zsh不支持。
字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。
Test和[]中, 整数比较可以使用-eq,-gt这类形式。
1.1.2.1.1 在bash中
[csdn ~]$ i=1; let i++; echo i=$i; j=12;let j--;echo j=$j
i=2
j=11
[csdn ~]$ [ $i -lt $j ]
[csdn ~]$ echo $?
0
[csdn ~]$ [ $i -gt $j ]
[csdn ~]$ echo $?
1
1.1.2.1.2 在zsh中
csdn @ edu $ i=1; let i++; echo i=$i; j=12;let j--;echo j=$j
i=2
j=11
csdn @ edu $ [ $i -lt $j ]
csdn @ edu $ echo $?
0
csdn @ edu $ [ $i -gt $j ]
csdn @ edu $ echo $?
1
在大多编程变语言中,对Linux shell中的整数比较,是否直接可用使用大于号(>)和小于号(<)呢?
1.1.2.1.1在bash中
[csdn ~]$ i=1; let i++; echo i=$i; j=12;let j--;echo j=$j
i=2
j=11
[csdn ~]$ echo $[ i > j ]
0
[csdn ~]$ echo $[ i < j ]
1
[csdn ~]$ echo $[ i \< j ]
bash: i \< j : syntax error: invalid arithmetic operator (error token is "\< j ")
[csdn ~]$ [ i \< j ]
[csdn ~]$ echo $?
0
[csdn ~]$ [ i \> j ]
[csdn ~]$ echo $?
1
在上面的实例中,我们定义了整数变量i和j,
先直接使用 > 和 < 来比较i和j,结果分别是0和1,这个结果按字符串来比较是对的,但按整数来比较是错误的。
接着我们使用 \< 和 \> 来对i和j进行比较,结果分别是0和1,正确。
以下是按字符串来比较的结果。
[csdn ~]$ i='2'; j="11"
[csdn ~]$ echo $[ i > j ]
0
[csdn ~]$ echo $[ i < j ]
1
1.1.2.1.2 在zsh中
csdn @ edu $ i=1; let i++; echo i=$i; j=12;let j--;echo j=$j
i=2
j=11
csdn @ edu $ echo $[ j > j ]
0
csdn @ edu $ echo $[ j < j ]
0
csdn @ edu $ echo $[ j \< j ]
zsh: bad math expression: illegal character: \
csdn @ edu $ echo $[ j \> j ]
zsh: bad math expression: illegal character: \
在上面的实例中,我们同样是定义了整数变量i和j,
先直接使用 > 和 < 来比较i和j,结果都是0,显示有问题。
接着我们使用 \< 和 \> 来对i和j进行比较,结果zsh不支持。
1.1.3.1 在bash中
[csdn ~]$ s1='a';s2='b';s3='a'
[csdn ~]$ [ $s1 == $s2 -o $s1 == $s3 ]
[csdn ~]$ echo $?
0
[csdn ~]$ [ $s1 == $s2 ] || [ $s1 == $s3 ]
[csdn ~]$ echo $?
0
[csdn ~]$ [ $s1 == $s2 -a $s1 == $s3 ]
[csdn ~]$ echo $?
1
[csdn ~]$ [ $s1 == $s2 ] && [ $s1 == $s3 ]
[csdn ~]$ echo $?
1
在上面的实例中,我们先定义了三个字符串变量: s1='a';s2='b';s3='a'
然后执行 [ $s1 == $s2 -o $s1 == $s3 ] , s1 == $s2 结果为1,$s1 == $s3结果为0,由于我们使用的是 -o (or ),所以结果为0
接着用命令 echo $? 来显示结果:0
然后的 [ $s1 == $s2 ] || [ $s1 == $s3 ] 和 [ $s1 == $s2 -o $s1 == $s3 ]是一样的。
接着执行 [ $s1 == $s2 -a $s1 == $s3 ] ,s1 == $s2 结果为1,$s1 == $s3结果为0,由于我们使用的是 -a (and ),所以结果为1
最后用命令 echo $? 来显示结果:0
1.1.3.2 在zsh中
csdn @ edu zsh $ s1='a';s2='b';s3='a'
csdn @ edu zsh $ [ $s1 == $s2 -o $s1 == $s3 ]
zsh: = not found
csdn @ edu zsh $ [ $s1 = $s2 -o $s1 = $s3 ]
csdn @ edu zsh $ echo $?
0
csdn @ edu zsh $ [ $s1 == $s2 ] || [ $s1 == $s3 ]
zsh: = not found
csdn @ edu zsh $ [ $s1 = $s2 ] || [ $s1 = $s3 ]
csdn @ edu zsh $ echo $?
0
csdn @ edu zsh $ [ $s1 = $s2 -o $s1 = $s3 ]
csdn @ edu zsh $ echo $?
0
csdn @ edu zsh $ [ $s1 = $s2 ] && [ $s1 = $s3 ]
csdn @ edu zsh $ echo $?
1
上面的实例与bash中是一样的,不过zsh不支持 == ,我们改为 = 。
对数组来说,中括号可以用来按下标索引访问数组元素。
1.2.1 在bash中
[csdn ~]$ a=(1 2 3)
[csdn ~]$ echo ${a[1]}
2
[csdn ~]$ echo ${a[*]}
1 2 3
在上面实例中,我们先定义数组 a=(1 2 3)
然后用命令 echo ${a[1]} 显示数组中的第2个元素,bash中数组下标从0开始。
接着用命令 echo ${a[*]} 显示数组中的所有元素。
1.2.2 在zsh中
csdn @edu zsh $ a=(1 2 3)
csdn @edu zsh $ echo $a[1]
1
csdn @edu zsh $ echo $a[*]
1 2 3
csdn @edu zsh $ echo ${a[1]}
1
csdn @edu zsh $ echo ${a[*]}
1 2 3
在上面实例中,我们先定义数组 a=(1 2 3)
然后用命令 echo ${a[1]} 显示数组中的第1个元素,bash中数组下标从1开始。
接着用命令 echo ${a[*]} 显示数组中的所有元素。
[[ ]]是 Shell 内置关键字,它的功能和 [] 或 test 命令类似,也用来检测某个条件是否成立。
[[ ]] 是 [] 或 test 的升级版,对细节进行了优化,并且扩展了一些功能。
2.1.1 在bash中
[csdn ~]$ s1='a';s2='b';s3='a'
[csdn ~]$ [ $s1 = $s2 || $s1 = $s3 ]
bash: [: missing `]'
bash: a: command not found
[csdn ~]$ [[ $s1 = $s2 || $s1 = $s3 ]]
[csdn ~]$ echo $?
0
[csdn ~]$ [[ $s1 = $s2 -o $s1 = $s3 ]]
bash: syntax error in conditional expression
bash: syntax error near `-o'
[csdn ~]$ [ $s1 = $s2 && $s1 = $s3 ]
bash: [: missing `]'
[csdn ~]$ [[ $s1 = $s2 && $s1 = $s3 ]]
[csdn ~]$ echo $?
1
[csdn ~]$ [[ $s1 = $s2 -a $s1 = $s3 ]]
bash: syntax error in conditional expression
bash: syntax error near `-a'
2.1.2 在zsh中
csdn @ edu zsh $ s1='a';s2='b';s3='a'
csdn @ edu zsh $ [ $s1 = $s2 || $s1 = $s3 ]
[: ']' expected
zsh: command not found: a
csdn @ edu zsh $ [[ $s1 = $s2 || $s1 = $s3 ]]
csdn @ edu zsh $ echo $?
0
csdn @ edu zsh $ [[ $s1 = $s2 -o $s1 = $s3 ]]
zsh: condition expected: $s1
csdn @ edu zsh $ [ $s1 = $s2 && $s1 = $s3 ]
[: ']' expected
csdn @ edu zsh $ [[ $s1 = $s2 && $s1 = $s3 ]]
csdn @ edu zsh $ echo $?
1
csdn @ edu zsh $ [[ $s1 = $s2 -a $s1 = $s3 ]]
zsh: condition expected: $s1
在 [[ ]] 中支持使用 && 和 ||,不支持 -o 和 -a。
在 Shell [[ ]] 中,可以使用=~来检测字符串是否符合某个正则表达式,其用法为:
[[ 字符串 =~ 正则表达式 ]]
例如:
2.2.1 在bash中
[csdn ~]$ s="12345"; [[ $s =~ ^[0-9]*$ ]]; echo $?
0
[csdn ~]$ s="12345abc"; [[ $s =~ ^[0-9]*$ ]]; echo $?
1
[csdn ~]$ s="12345"; [[ $s =~ ^[a-z]*$ ]]; echo $?
1
[csdn ~]$ s="abc"; [[ $s =~ ^[a-z]*$ ]]; echo $?
0
2.2.2 在zsh中
csdn @ edu zsh $ s="12345"; [[ $s =~ ^[0-9]*$ ]]; echo $?
0
csdn @ edu zsh $ s="12345abc"; [[ $s =~ ^[0-9]*$ ]]; echo $?
1
csdn @ edu zsh $ s="12345"; [[ $s =~ ^[a-z]*$ ]]; echo $?
1
csdn @ edu zsh $ s="abc"; [[ $s =~ ^[a-z]*$ ]]; echo $?
0
2.2.3 注意
为了确保[[]]取得正确结果,其中的变量名要加上$前缀。
在bash中:
[csdn ~]$ s="12345"; [[ s =~ ^[0-9]*$ ]]; echo $?
1
[csdn ~]$ s="12345"; [[ $s =~ ^[0-9]*$ ]]; echo $?
0
[csdn ~]$ s="abc"; [[ s =~ ^[0-9]*$ ]]; echo $?
1
[csdn ~]$ s="abc"; [[ $s =~ ^[0-9]*$ ]]; echo $?
1
[csdn ~]$ s="abc"; [[ s =~ ^[a-z]*$ ]]; echo $?
0
[csdn ~]$ s="abc"; [[ $s =~ ^[a-z]*$ ]]; echo $?
0
[csdn ~]$ s="123"; [[ s =~ ^[a-z]*$ ]]; echo $?
0
[csdn ~]$ s="123"; [[ $s =~ ^[a-z]*$ ]]; echo $?
1