Linux中用于数值、字符串和文件比较的方法
1 数值比较
使用test命令最常见的情形是对两个数值进行比较。表12-1列出了测试两个值时可用的条件参数。
表12-1 test命令的数值比较功能
| 比 较 | 描 述 |
|---|---|
| n1 -eq n2 | 检查n1是否与n2相等 |
| n1 -ge n2 | 检查n1是否大于或等于n2 |
| n1 -gt n2 | 检查n1是否大于n2 |
| n1 -le n2 | 检查n1是否小于或等于n2 |
| n1 -lt n2 | 检查n1是否小于n2 |
| n1 -ne n2 | 检查n1是否不等于n2 |
数值条件测试可以用在数字和变量上。这里有个例子。
$ cat numeric_test.sh
#!/bin/bash
# Using numeric test evaluations
#
value1=10
value2=11
#
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater than 5"
fi
#
if [ $value1 -eq $value2 ]
then
echo "The values are equal"
else
echo "The values are different"
fi
#
$
第一个条件测试:
if [ $value1 -gt 5 ]
测试变量value1的值是否大于5。第二个条件测试:
if [ $value1 -eq $value2 ]
测试变量value1的值是否和变量value2的值相等。两个数值条件测试的结果和预想一致。
$ ./numeric_test.sh
The test value 10 is greater than 5
The values are different
$
但是涉及浮点值时,数值条件测试会有一个限制。
$ cat floating_point_test.sh
#!/bin/bash
# Using floating point numbers in test evaluations
#
value1=5.555
#
echo "The test value is $value1"
#
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater than 5"
fi
#
$ ./floating_point_test.sh
The test value is 5.555
./floating_point_test.sh: line 8:
[: 5.555: integer expression expected
$
此例,变量value1中存储的是浮点值。接着,脚本对这个值进行了测试。显然这里出错了。记住,bash shell只能处理整数。如果你只是要通过echo语句来显示这个结果,那没问题。但是,在基于数字的函数中就不行了,例如我们的数值测试条件。最后一行就说明我们不能在test命令中使用浮点值。
2 字符串比较
条件测试还允许比较字符串值。比较字符串比较烦琐,你马上就会看到。表12-2列出了可用的字符串比较功能。
表12-2 字符串比较测试
| 比 较 | 描 述 |
|---|---|
| str1 = str2 | 检查str1是否和str2相同 |
| str1 != str2 | 检查str1是否和str2不同 |
| str1 < str2 | 检查str1是否比str2小 |
| str1 > str2 | 检查str1是否比str2大 |
| -n str1 | 检查str1的长度是否非0 |
| -z | str1 检查str1的长度是否为0 |
下面几节将会详细介绍不同的字符串比较功能。
2.1 字符串相等性
字符串的相等和不等条件不言自明,很容易看出两个字符串值是否相同。
$ cat test7.sh
#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER = $testuser ]
then
echo "Welcome $testuser"
fi
$
$ ./test7.sh
Welcome rich
$
字符串不等条件也可以判断两个字符串是否有相同的值。
记住,在比较字符串的相等性时,比较测试会将所有的标点和大小写情况都考虑在内。
2.2 字符串顺序
要测试一个字符串是否比另一个字符串大就是麻烦的开始。当要开始使用测试条件的大于或小于功能时,就会出现两个经常困扰shell程序员的问题:
- 大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名;
- 大于和小于顺序和sort命令所采用的不同。
在编写脚本时,第一条可能会导致一个不易察觉的严重问题。下面的例子展示了shell脚本编程初学者时常碰到的问题。
$ cat badtest.sh
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 > $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi
$
$ ./badtest.sh
baseball is greater than hockey
$ ls -l hockey
-rw-r--r-- 1 rich rich 0 Sep 30 19:08 hockey
$
这个脚本中只用了大于号,没有出现错误,但结果是错的。脚本把大于号解释成了输出重定向(参见第15章)。因此,它创建了一个名为hockey的件。由于重定向的顺利完成,test命令返回了退出状态码0,if语句便以为所有命令都成功结束了。要解决这个问题,就需要正确转义大于号。
$ cat test9.sh
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 \> $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi
$
$ ./test9.sh
baseball is less than hockey
$
现在的答案已经符合预期的了。
第二个问题更细微,除非你经常处理大小写字母,否则几乎遇不到。sort命令处理大写字母的方法刚好跟test命令相反。让我们在脚本中测试一下这个特性。
$ cat test9b.sh
!/bin/bash
testing string sort order
val1=Testing
val2=testing
if [ $val1 > \(val2 ]
then
echo "\)val1 is greater than \(val2"
else
echo "\)val1 is less than \(val2"
fi
\)
$ ./test9b.sh
Testing is less than testing
\(
\) sort testfile
testing
Testing
$
在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。当你将同样的字符串放进文件中并用sort命令排序时,小写字母会先出现。这是由各个命令使用的排序技术不同造成的。
比较测试中使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。sort命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺序中小写字母出现在大写字母前。
说明 test命令和测试表达式使用标准的数学比较符号来表示字符串比较,而用文本代码来表示数值比较。这个细微的特性被很多程序员理解反了。如果你对数值使用了数学运算符号,shell会将它们当成字符串值,可能无法得到正确的结果。
2.3 字符串大小
-n和-z可以检查一个变量是否含有数据。
$ cat test10.sh
#!/bin/bash
# testing string length
val1=testing
val2=''
#
if [ -n $val1 ]
then
echo "The string '$val1' is not empty"
else
echo "The string '$val1' is empty"
fi
#
if [ -z $val2 ]
then
echo "The string '$val2' is empty"
else
echo "The string '$val2' is not empty"
fi
$ ./test10.sh
The string 'testing' is not empty
The string '' is empty
$
这个例子创建了两个字符串变量。val1变量包含了一个字符串,val2变量包含的是一个空字符串。后续的比较如下:
if [ -n $val1 ]
判断val1变量是否长度非0,而它的长度正好非0,所以then部分被执行了。
if [ -z $var2 ]
判断val2变量是否长度为0,而它正好长度为0,所以then部分被执行了。
空的和未初始化的变量会对shell脚本测试造成灾难性的影响。如果不是很确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过-n或-z来测试一下变量是否含有值。
2.3 文件比较
最后一类比较测试很有可能是shell编程中最为强大、也是用得最多的比较形式。它允许你测试Linux文件系统上文件和目录的状态。表12-3列出了这些比较。
表12-3 test命令的文件比较功能
| 比 较 | 描 述 |
|---|---|
| -d file | 检查file是否存在并是一个目录 |
| -e file | 检查file是否存在 |
| -f file | 检查file是否存在并是一个文件 |
| -r file | 检查file是否存在并可读 |
| -s file | 检查file是否存在并非空 |
| -w file | 检查file是否存在并可写 |
| -x file | 检查file是否存在并可执行 |
| -O file | 检查file是否存在并属当前用户所有 |
| -G file | 检查file是否存在并且默认组与当前用户相同 |
| file1 -nt file2 | 检查file1是否比file2新 |
| file1 -ot file2 | 检查file1是否比file2旧 |
例如:检查文件日期
最后一组方法用来对两个文件的创建日期进行比较。这在编写软件安装脚本时非常有用。有时候,你不会愿意安装一个比系统上已有文件还要旧的文件。-nt比较会判定一个文件是否比另一个文件新。如果文件较新,那意味着它的文件创建日期更近。-ot比较会判定一个文件是否比另一个文件旧。如果文件较旧,意味着它的创建日期
更早。
$ cat test20.sh
#!/bin/bash
# testing file dates
#
if [ test19.sh -nt test18.sh ]
then
echo "The test19 file is newer than test18"
else
echo "The test18 file is newer than test19"
fi
if [ test17.sh -ot test19.sh ]
then
echo "The test17 file is older than the test19 file"
fi
$
$ ./test20.sh
The test19 file is newer than test18
The test17 file is older than the test19 file
$
$ ls -l test17.sh test18.sh test19.sh
-rwxrw-r-- 1 rich rich 167 2014-07-30 16:31 test17.sh
-rwxrw-r-- 1 rich rich 185 2014-07-30 17:46 test18.sh
-rwxrw-r-- 1 rich rich 167 2014-07-30 17:50 test19.sh
浙公网安备 33010602011771号