LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 145|回复: 0

Shell脚本深入教程:Bash测试命令

[复制链接]
发表于 2023-12-14 13:47:10 | 显示全部楼层 |阅读模式

Bash测试命令
test命令或功能等价的Bash内置命令[ ]可以做条件测试,如果测试的结果为True,则退出状态码为0。

此外,还可以使用[[]]来做条件测试,它比test多一个正则匹配的功能。此外,let、$[]、$(())也可以做条件测试。但我的建议是只掌握一个测试方式,要么掌握[]测试,要么掌握[[]]。我个人是习惯于使用[],并在很偶尔做正则测试的时候用[[]],但更多正则测试我还是使用echo+grep/perl来完成的。

这些条件测试常用在if、while语句中,也常用在cmd1 && cmd2 || cmd3格式的命令行中。

用法示例:

sh_file=test.sh
[ -x "$sh_file" ] && ./$sh_file || { echo "can't execute,exit...";exit 1; }
test -x "$sh_file" && ./$sh_file || { echo "can't execute,exit...";exit 1; }
[]和[[]]中的条件测试语句都需要和开闭中括号使用空格隔开,否则语法解析错误。

无测试内容
[  ]
test
没有任何测试内容时,直接返回false。

true和false命令
true命令直接返回true,即退出状态码为0。

false命令直接返回false,即退出状态码非0。

$ true
$ echo $?  # 0
$ false
$ echo $?  # 1
文件类测试
条件表达式        含义
-e file        文件是否存在(exist)
-f file        文件是否存在且为普通文件(file)
-d file        文件是否存在且为目录(directory)
-b file        文件是否存在且为块设备block device
-c file        文件是否存在且为字符设备character device
-S file        文件是否存在且为套接字文件Socket
-p file        文件是否存在且为命名管道文件FIFO(pipe)
-L file        文件是否存在且是一个链接文件(Link)
测试是否是终端
if [ -t 1 ]; then # is terminal?
  BOLD="\e[1m";      DIM="\e[2m";
  RED="\e[0;31m";    RED_BOLD="\e[1;31m";
  YELLOW="\e[0;33m"; YELLOW_BOLD="\e[1;33m";
  GREEN="\e[0;32m";  GREEN_BOLD="\e[1;32m";
  BLUE="\e[0;34m";   BLUE_BOLD="\e[1;34m";
  GREY="\e[37m";     CYAN_BOLD="\e[1;36m";
  RESET="\e[0m";
fi
文件属性类测试
条件表达式        含义
-r file        文件是否存在且当前用户可读
-w file        文件是否存在且当前用户可写
-x file        文件是否存在且当前用户可执行
-s file        文件是否存在且大小大于0字节,即检测文件是否非空文件
-N file        文件是否存在,且自上次read后是否被modify
两文件之间的比较
条件表达式        含义
file1 -nt file2        (newer than)判断file1是否比file2新
file1 -ot file2        (older than)判断file1是否比file2旧
file1 -ef file2        (equal file)判断file1与file2是否为同一文件
数值大小比较
条件表达式        含义
int1 -eq int2        两数值相等(equal)
int1 -ne int2        两数值不等(not equal)
int1 -gt int2        n1大于n2(greater than)
int1 -lt int2        n1小于n2(less than)
int1 -ge int2        n1大于等于n2(greater than or equal)
int1 -le int2        n1小于等于n2(less than or equal)
字符串比较
条件表达式        含义
-z str        (zero)判定字符串是否为空?str为空串,则true
str
-n str        判定字符串是否非空?str为串,则false。注:-n可省略
str1 = str2
str1 == str2        str1和str2是否相同,相同则返回true。『==』和『=』等价
str1 != str2        str1是否不等于str2,若不等,则返回true
str1 > str2        str1字母顺序是否大于str2,若大于则返回true
str1 < str2        str1字母顺序是否小于str2,若小于则返回true
逻辑运算符
条件表达式        含义
-a或&&        (and)两表达式同时为true时才为true。
『-a』只能在test或[]中使用,&&只能在[[]]中使用
-o或||        (or)两表达式任何一个true则为true。
『-o』只能在test或[]中使用,||只能在[[]]中使用
!        对表达式取反
( )        改变表达式的优先级,为了防止被shell解析,应加上反斜线转义\( \)
对于逻辑与和逻辑或,下面实现的效果是等价的:

[ $a -gt 1 -a $a -lt 5 ]
[ $a -gt 1 ] && [ $a -lt 5 ]

[ $a -gt 5 -o $a -lt 1 ]
[ $a -gt 5 ] || [ $a -lt 1 ]
双中括号测试[[]]
双中括号也能进行测试,测试功能和[]相比只有少数不同,但它有一个非常好用的功能:正则测试,正则测试后还能获取正则匹配到的内容。

我个人通常是习惯使用[]进行测试的,只有在需要正则测试的时候才很偶尔使用[[]],大多数正则测试还是使用echo + grep/perl。

这里我介绍下[[]]的正则测试功能,大家可以根据自己的喜好来决定使用哪种方式。

在[[]]中,使用=~符号开启正则测试功能,它使用的是扩展正则。

[[ "hello123world" =~ [0-9]+ ]]
echo $?   # 0
=~左边是待匹配的字符串或变量,右边是正则表达式。

正则表达式部分默认不加引号包围,如果加引号(无论是单双引号)包围,将和反斜线\功能一样,对整个正则表达式进行转义。

比如:

# 匹配成功,正则元字符点能匹配任意字符
[[ "abc.jpg" =~ .b ]]
echo $?   # 0

# 引号包围的正则元字符点被转义,它只能匹配点字符,不能再匹配任意字符
# 所以,下面匹配失败
[[ "abc.jpg" =~ ".b" ]]
echo $?   # 1

# 正则元字符点被反斜线转义,也只能匹配点字符
# 所以匹配失败
[[ "abc.jpg" =~ \.b ]]
echo $?   # 1


例如:

[[ "abc1234,789" =~ [a-z]{1,}([0-9]+),([0-9]+) ]]
echo ${!BASH_REMATCH[@]}   # 0 1 2
echo ${BASH_REMATCH[0]}   # abc1234,789
echo ${BASH_REMATCH[1]}   # 1234
echo ${BASH_REMATCH[2]}   # 789
条件测试注意事项
1.无论是[]还是[[]],都建议对其内变量、字符串使用双引号包围。换句话说,能做字符串比较的时候,不要用数值比较。

例如:

name="Ma long"
[ $name = "Ma long" ]
上面的测试语句将报错,因为在变量替换阶段,$name被替换为『Ma long』,但它们没有在引号内,于是进行单词拆分,这就等价于执行的是[ Ma long = "Ma long" ],显然这是错误的语法。所以,建议加上双引号:

[ "$name" = "Ma long" ]
2.数值比较时,建议双方同时加0,避免变量为空时报错。

例如,变量a为空,下面的表达式是错误的。因为它被shell解析后相当于[ -eq 7 ],而这是错误的语法。

$ [ $a -eq 7 ]
-bash: [: -eq: unary operator expected
采取第一种建议,将$a使用引号包围的话,还是错的。因为被shell解析后相当于[ "" -eq 7 ],字符串和数值无法比较。注意这里的报错和上面的错误信息不一样。

$ [ "$a" -eq 7 ]
-bash: [: : integer expression expected
所以最好的方法是将它改为字符串来测试,或者双方同时加0,由于此处有一方是常量数值,所以只需为变量部分加0即可。

[ "$a" = "7" ]
[ $[a+0] -le 8 ]
3.当变量可能为空的时候,强烈建议在变量的基础上加上其他辅助字符串。

上面的语句虽然能正确测试。其实更安全的方法是采用下面的形式:

[ "a$a" = "a7" ]   # 判断a是否为7
[ "a$a" = "a" ]    # 判断a是否为空
[ ! -z "$a" -a "a$a" = "a7" ]  # a不为空且a=7时才为真
4.另外,在[]和[[]]中,每个地方都有空格。这不是书写建议,而是强制要求的格式。

文章链接: https://www.junmajinlong.com/shell/script_course/shell_test/
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表