字符串顺序及大小比较注意事项
字符串顺序
当要使用测试条件的大于或小于功能时,会出现两个经常困扰 shell 程序员的问题
1. 大于号和小于号必须转义,否则 shell 会将大于和小于号(>, <)当作重定向符号,把字符串值当作文件名
#cat badtest.sh
#!/bin/bash
# mis-using string comparisons
#
v1=baseball
v2=hockey
#
if [ $v1 > $v2 ]
then
echo "$v1 is greater than $v2"
else
echo "$v1 is less than $v2"
fi
#sh badtest.sh
baseball is greater than hockey
badtest.sh 脚本中使用大于号来比较字符串,执行脚本未报错,但结果是错的。脚本将大于号解释成输出重定向。因此创建了一个名为 hockey 的文件。由于重定向的完成,test 命令返回退出状态码 0, if 语句便以为所有命令成功结束,从而执行 then 部分语句。
要解决此问题,需要对大于号进行转义
#cat test9.sh
#!/bin/bash
# mis-using string comparisons
#
v1=baseball
v2=hockey
#
if [ $v1 \> $v2 ]
then
echo "$v1 is greater than $v2"
else
echo "$v1 is less than $v2"
fi
#sh test9.sh
baseball is less than hockey
- 大于和小于顺序和 sort 命令所采用的不同
sort 命令处理大写字母的方法和 test 命令相反
#cat test9b.sh
#!/bin/bash
# testing string sort order
v1=Testing
v2=testing
#
if [ $v1 \> $v2 ]
then
echo "$v1 is greater than $v2"
else
echo "$v1 is less than $v2"
fi
#sh test9b.sh
Testing is less than testing
#cat testfile
Testing
testing
#sort testfile
testing
Testing
在脚本 test9b.sh 的比较测试中,大写字母被认为是小于小写字母的。但 sort 命令对 testfile 文件内容的排序与之相反,当做同样的字符串放进文件中并用sort排序时,小写字母会先出现。
比较测试和 sort 命令结果不一致原因
二者所采用的排序技术不同,比较测试遵循的是每个字符的ASCII数值,而sort命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺序中小写字母出现在大写字母前
说明
test命令和测试表达式使用标准的数学比较符号来表示字符串比较,而用文本代码来表示数值比较。这个细微的特性被很多程序员理解反了。如果你对数值使用了数学运算符号, shell会将它们当成字符串值,可能无法得到正确的结果。
字符串大小
-n and -z
可检查一个变量是否含有数据
比较 | 描述 |
---|---|
-n str1 | 检查str1的长度是否大于0 |
-z str1 | 检查str1的长度是否等于0 |
变量分为三种情况
变量 | 值 |
---|---|
1 | 有值,如'string' |
2 | 为空,如'' |
3 | 未定义变量 |
测试方法
对变量的三种情况分别以选项-n and -z
测试
#cat test10.sh
#!/bin/bash
# testing string length
var1=testing
var2=''
#
if [ -n $var1 ]
then
echo "-n option, The string '$var1' is not empty"
else
echo "-n option, The string '$var1' is empty"
fi
if [ -z $var1 ]
then
echo "-z option, The string '$var1' length is 0"
else
echo "-z option, The string '$var1' is not empty"
fi
#
if [ -n $var2 ]
then
echo "-n option, The string '$var2' is not empty'"
else
echo "-n option, The string '$var2' is empty"
fi
if [ -z $var2 ]
then
echo "-z option, The string '$var2' length is 0"
else
echo "-z option, The string '$var2' is not empty"
fi
#
if [ -n $var3 ]
then
echo "-n option, The string '$var3' is not empty"
else
echo "-n option, The string '$var3' is empty"
fi
if [ -z $var3 ]
then
echo "The string '$var3' length is 0"
else
echo "The string '$var3' is not empty"
fi
这个例子创建了两个字符串变量。 val1变量包含了一个字符串, val2变量包含的是一个空
字符串。后续的比较如下:
if [ -n $val1 ]
判断val1变量是否长度非0,而它的长度正好非0,所以then部分被执行了。
if [ -z $val1 ]
判断val1变量是否长度为0,而它的长度非0,所以else部分被执行了。
if [ -n $var2 ]
if [ -z $var2 ]
判断val2变量是否长度为0,而它正好长度为0,所以then部分被执行了。
if [ -n $val3 ]
if [ -z $val3 ]
判断val3变量是否长度为0。这个变量并未在shell脚本中定义过,所以它的字符串长度仍然为0,尽管它未被定义过。
存在问题
对空字符串和未定义变量的长度计算需注意
if [ -n $var2 ]
if [ -n $var3 ]
空字符串长度比较测试
#cat empty_str_len.sh
#!/bin/bash
#
v1=''
#
if [ -n $v1 ]
then
echo "The length of $v1 is greater than 0"
else
echo "The length of $v1 is less than 0"
fi
#sh empty_str_len.sh
The length of is greater than 0
未定义变量长度比较测试
#cat empty_str_len.sh
#!/bin/bash
#
v1=''
#
if [ -n $v2 ]
then
echo "The length of $v1 is greater than 0"
else
echo "The length of $v1 is less than 0"
fi
#sh empty_str_len.sh
The length of is greater than 0
结论
-n str
认为空字符串和未定义变量的长度是大于0的
窍门
空的和未初始化的变量会对shell脚本测试造成灾难性的影响。如果不是很确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过-n或-z来测试一下变量是否含有值。