跳至内容

Bash - 测试


目标:在本章中,您将学会如何

✔ 处理返回码;
✔ 测试和比较文件;
✔ 测试变量、字符串和整数;
✔ 对整数执行运算;

🏁 linux, 脚本, bash, 变量

知识⭐ ⭐
复杂性: ⭐ ⭐ ⭐

阅读时间:10 分钟


Shell 执行的命令完成后,都会返回一个返回码(也称为状态退出码)。

  • 如果命令正确执行,约定状态码为
  • 如果命令在执行过程中遇到问题,其状态码将为非零值。原因有很多:缺少访问权限、文件丢失、输入错误等。

您应该查阅 man command 手册,以了解开发人员提供的返回码的不同值。

返回码不直接可见,但存储在一个特殊变量中:$?

mkdir directory
echo $?
0
mkdir /directory
mkdir: unable to create directory
echo $?
1
command_that_does_not_exist
command_that_does_not_exist: command not found
echo $?
127

注意

使用 echo 命令显示 $? 变量的内容,应在您要评估的命令之后立即执行,因为该变量在每次执行命令、命令或脚本后都会更新。

技巧

由于 $? 的值在每次命令执行后都会改变,因此最好将其值放入一个将在之后使用的变量中,用于测试或显示消息。

ls no_file
ls: cannot access 'no_file': No such file or directory
result=$?
echo $?
0
echo $result
2

在脚本中创建返回码也是可能的。为此,只需为 exit 命令添加一个数字参数即可。

bash # to avoid being disconnected after the "exit 2
exit 123
echo $?
123

除了命令的正确执行,shell 还提供了对多种模式进行测试的可能性

  • 文件:存在性、类型、权限、比较;
  • 字符串:长度、比较;
  • 整数:值、比较。

测试结果

  • $?=0:测试正确执行并为真;
  • $?=1:测试正确执行但为假;
  • $?=2:测试未正确执行。

测试文件类型

用于文件的 test 命令语法

test [-d|-e|-f|-L] file

[ -d|-e|-f|-L file ]

注意

请注意,在 [ 之后和 ] 之前有一个空格。

文件测试命令选项

选项 观察
-e 测试文件是否存在
-f 测试文件是否存在且为普通文件
-d 检查文件是否存在且为目录
-L 检查文件是否存在且为符号链接
-b 检查文件是否存在且为块设备特殊文件
-c 检查文件是否存在且为字符设备特殊文件
-p 检查文件是否存在且为命名管道(FIFO)
-S 检查文件是否存在且为套接字
-t 检查文件是否存在且为终端
-r 检查文件是否存在且可读
-w 检查文件是否存在且可写
-x 检查文件是否存在且可执行
-g 检查文件是否存在且设置了 SGID
-u 检查文件是否存在且设置了 SUID
-s 测试文件是否存在且非空(大小 > 0 字节)

示例

test -e /etc/passwd
echo $?
0
[ -w /etc/passwd ]
echo $?
1

已创建一种内部命令,某些 shell(包括 bash)支持该命令,它比外部命令 test 更现代,并提供了更多功能。

[[ -s /etc/passwd ]]
echo $?
1

注意

因此,本章其余部分将使用内部命令。

比较两个文件

比较两个文件也是可能的

[[ file1 -nt|-ot|-ef file2 ]]
选项 观察
-nt 测试第一个文件是否比第二个新
-ot 测试第一个文件是否比第二个旧
-ef 测试第一个文件是否是第二个文件的硬链接

测试变量

可以测试变量

[[ -z|-n $variable ]]
选项 观察
-z 测试变量是否为空
-n 测试变量是否非空

测试字符串

比较两个字符串也是可能的

[[ string1 =|!=|<|> string2 ]]

示例

[[ "$var" = "Rocky rocks!" ]]
echo $?
0
选项 观察
= 测试第一个字符串是否等于第二个
!= 测试第一个字符串是否与第二个不同
< 测试第一个字符串在 ASCII 顺序上是否在第二个之前
> 测试第一个字符串在 ASCII 顺序上是否在第二个之后

整数比较

测试整数的语法

[[ "num1" -eq|-ne|-gt|-lt "num2" ]]

示例

var=1
[[ "$var" -eq "1" ]]
echo $?
0
var=2
[[ "$var" -eq "1" ]]
echo $?
1
选项 观察
-eq 测试第一个数字是否等于第二个
-ne 测试第一个数字是否不等于第二个
-gt 测试第一个数字是否大于第二个
-lt 测试第一个数字是否小于第二个

注意

由于 shell 将数值视为普通字符(或字符串),因此对字符的测试可能产生相同的结果,无论它被视为数值还是非数值。

test "1" = "1"
echo $?
0
test "1" -eq "1"
echo $?
0

但测试结果的意义将不同

  • 在第一种情况下,它意味着两个字符在 ASCII 表中具有相同的值。
  • 在第二种情况下,它意味着两个数字相等。

组合测试

组合测试允许您在一个命令中执行多个测试。可以多次测试同一个参数(文件、字符串或数值),也可以测试不同的参数。

[ option1 argument1 [-a|-o] option2 argument 2 ]
ls -lad /etc
drwxr-xr-x 142 root root 12288 sept. 20 09:25 /etc
[ -d /etc -a -x /etc ]
echo $?
0
选项 观察
-a AND:当所有模式都为真时,测试为真。
-o OR:当至少一个模式为真时,测试为真。

对于内部命令,最好使用此语法

[[ -d "/etc" && -x "/etc" ]]

测试可以使用圆括号 ( ) 进行分组,以赋予它们优先级。

(TEST1 -a TEST2) -a TEST3

! 字符用于执行与选项请求的测试相反的测试

test -e /file # true if file exists
! test -e /file # true if file does not exist

数值运算

expr 命令执行整数运算。

expr num1 [+] [-] [\*] [/] [%] num2

示例

expr 2 + 2
4

警告

请注意在运算符两侧加上空格。如果忘记,您将收到错误消息。对于乘法,乘号 * 前面会加上 \,以避免被错误解释。

选项 观察
+ 加法
- 减法
\* 乘法
/ 除法商
% 除法模

typeset 命令

typeset -i 命令将变量声明为整数。

示例

typeset -i var1
var1=1+1
var2=1+1
echo $var1
2
echo $var2
1+1

let 命令

let 命令测试字符是否为数字。

示例

var1="10"
var2="AA"
let $var1
echo $?
0
let $var2
echo $?
1

警告

let 命令在评估数值 0 时不返回一致的返回码。

let 0
echo $?
1

let 命令还允许您执行数学运算

let var=5+5
echo $var
10

let 可以被 $(( )) 替换。

echo $((5+2))
7
echo $((5*2))
10
var=$((5*3))
echo $var
15

作者:Antoine Le Morvan

贡献者:Steven Spencer, Ganna Zhyrnova