条件判断
最后更新于:2022-04-02 03:53:33
[TOC]
## 中括号 / 双中括号 区别
相同点
1. 两个符号左右都要有空格分隔
2. 内部操作符与操作变量之间要有空格:如 `[[ "a" = "b" ]]`
3. 内部字符串或者${}变量尽量使用”” 双引号扩住
单中括号 [ ]
1. 字符串比较中,> < 需要写成 `\>` `\<` 进行转义
1. [ ] 中可以使用 –a –o 进行逻辑运算
1. [ ] 是bash 内置命令
双中括号
1. 字符串比较中,可以直接使用 > < 无需转义
1. [[ ]] 内部可以使用 && || 进行逻辑运算
1. [[ ]] 是bash keyword:[[ is a shell keyword
## if 结构
```
if commands; then
commands
[elif commands; then
commands...]
[else
commands]
fi
// 多个条件
if [ commands ] && [ commands ] ;then
// code
fi
```
示例
```
if test $USER = "foo"; then
echo "Hello foo."
else
echo "You are not foo."
fi
```
## test 命令
```
# 写法一
test expression
# 写法二
[ expression ]
# 写法三
[[ expression ]]
```
```
# 写法一
if test -e /tmp/foo.txt ; then
echo "Found foo.txt"
fi
# 写法二
if [ -e /tmp/foo.txt ] ; then
echo "Found foo.txt"
fi
# 写法三
if [[ -e /tmp/foo.txt ]] ; then
echo "Found foo.txt"
fi
```
### && || 逻辑运算
```
$ command1 && command2 // command1 成功执行 command2
$ command1 || command2 // command1 失败执行 command2
```
示例1
```
[ -d temp ] || mkdir temp
```
示例2
```
[[ -d "$dir_name" ]] && cd "$dir_name" && rm *
```
## 判断表达式
### 文件 / 目录 判断
* `[ -d file ]`:如果 file 存在并且是一个目录,则为`true`。
* `[ -e file ]`:如果 file 存在,则为`true`。
* `[ -f file ]`:如果 file 存在并且是一个普通文件,则为`true`。
* `[ -r file ]`:如果 file 存在并且可读(当前用户有可读权限),则为`true`。
* `[ -s file ]`:如果 file 存在且其长度大于零,则为`true`。
* `[ -w file ]`:如果 file 存在并且可写(当前用户拥有可写权限),则为`true`。
* `[ -x file ]`:如果 file 存在并且可执行(有效用户有执行/搜索权限),则为`true`。
* `[ file1 -nt file2 ]`:如果 FILE1 比 FILE2 的更新时间最近,或者 FILE1 存在而 FILE2 不存在,则为`true`。
* `[ file1 -ot file2 ]`:如果 FILE1 比 FILE2 的更新时间更旧,或者 FILE2 存在而 FILE1 不存在,则为`true`。
* `[ FILE1 -ef FILE2 ]`:如果 FILE1 和 FILE2 引用相同的设备和 inode 编号,则为`true`。
### 字符串判断
* `[ string ]`:如果`string`不为空(长度大于0),则判断为真。
* `[ -n string ]`:如果字符串`string`的长度大于零,则判断为真。
* `[ -z string ]`:如果字符串`string`的长度为零,则判断为真。
* `[ string1 = string2 ]`:如果`string1`和`string2`相同,则判断为真。
* `[ string1 == string2 ]`等同于`[ string1 = string2 ]`。
* `[ string1 != string2 ]`:如果`string1`和`string2`不相同,则判断为真。
* `[ string1 '>' string2 ]`:如果按照字典顺序`string1`排列在`string2`之后,则判断为真。
* `[ string1 '<' string2 ]`:如果按照字典顺序`string1`排列在`string2`之前,则判断为真。
### 整数判断
* `[ integer1 -eq integer2 ]`:如果`integer1`等于`integer2`,则为`true`。
* `[ integer1 -ne integer2 ]`:如果`integer1`不等于`integer2`,则为`true`。
* `[ integer1 -le integer2 ]`:如果`integer1`小于或等于`integer2`,则为`true`。
* `[ integer1 -lt integer2 ]`:如果`integer1`小于`integer2`,则为`true`。
* `[ integer1 -ge integer2 ]`:如果`integer1`大于或等于`integer2`,则为`true`。
* `[ integer1 -gt integer2 ]`:如果`integer1`大于`integer2`,则为`true`。
### 正则判断
语法
`[[ string1 =~ regex ]]`
示例
```
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
echo "INT is an integer."
exit 0
else
echo "INT is not an integer." >&2
exit 1
fi
```
### 算术判断
```
if ((3 > 2)); then
echo "true"
fi
```
```
if [[ ! -d "$dir_name" ]]; then
echo "No such directory: '$dir_name'" >&2
exit 1
fi
if ! cd "$dir_name"; then
echo "Cannot cd to '$dir_name'" >&2
exit 1
fi
if ! rm *; then
echo "File deletion failed. Check results" >&2
exit 1
fi
```
## case 结构
格式
```
case expression in
pattern )
commands ;;
pattern )
commands ;;
...
esac
```
case的匹配模式可以使用各种通配符
```
a):匹配a。
a|b):匹配a或b。
[[:alpha:]]):匹配单个字母。
???):匹配3个字符的单词。
*.txt):匹配.txt结尾。
*):匹配任意输入,通过作为case结构的最后一个模式
```
Bash 4.0之前,case结构只能匹配一个条件,然后就会退出case结构。Bash 4.0之后,允许匹配多个条件,这时可以用;;&终止每个条件块
示例1
```
#! /bin/bash
echo -n "输入1~3 的数字"
read char
case $char in
1)echo 1;;
2)echo 2;;
3)echo 3;;
*)echo "输入不符合要求"
esac
```
示例2
```
#!/bin/bash
OS=$(uname -s)
case "$OS" in
FreeBSD) echo "This is FreeBSD" ;;
Darwin) echo "This is Mac OSX" ;;
AIX) echo "This is AIX" ;;
Minix) echo "This is Minix" ;;
Linux) echo "This is Linux" ;;
*) echo "Failed to identify this OS" ;;
esac
```
示例3
满足条件后终止匹配
```
read -n 1 -p "Type a character > "
echo
case $REPLY in
[[:upper:]]) echo "'$REPLY' is upper case." ;;&
[[:lower:]]) echo "'$REPLY' is lower case." ;;&
[[:alpha:]]) echo "'$REPLY' is alphabetic." ;;&
esac
```
';