所谓 结构化命令(structured command) 就是 根据条件 使脚本跳过某些语句的命令.
1 if-then-else 语句
最基本的结构化命令就是 if-then
语句:
# 如果command 的 返回状态码 是 0, 则程序会进入 if 并执行 then 后面的语句
if command
then
commands
fi
shell 的 if
语句和其他编程语言不太一样, 其他编程语言的if
语句一般都是判断一个 boolean
是 true
还是 false
, 而 shell 的 if
判断 一个命令的执行的返回状态码是否为0
, 为 0
就进入 if
语句, 不为 0
就跳过 if
语句.
if-then
亦可以写出下面格式:
# 分号;放在 command 后面, then 就可以和 if 放在一行了.
# 这种用法和 多个命令放在一行用分号分隔实现顺序处理 的逻辑是一样的
if command; then
commands
fi
if-then-else
语句格式:
if command; then
commands1
else
commands2
fi
示例1, if-then
:
$ cat temp.sh
#!/bin/bash
if pwd; then
echo "It worked"
fi
$ ./temp.sh
/home/miyan/test
It worked
示例2, if-then-else
:
$ cat temp.sh
#!/bin/bash
user="rosie"
if grep $user /etc/passwd; then
echo "$user exist."
else
echo "$user does not exist."
fi
$ ./temp.sh
rosie does not exist.
2 嵌套 if
嵌套 if
格式:
if command1; then
commands1
elif command2; then
commands2
fi
注意 shell 中没有 else if
, 只有 elif
.
elif
和 if
一样, if条件
后面必须加一个 then
语句.
3 test 命令
首先, 必须明确一点: if-then
语句的条件只能测试命令的退出状态码.
如果 test
命令中的条件成立, test
命令就会返回退出状态码 0
;
因此, 我们可以通过test
命令使 if-then
判断一下条件.
if-then
和 test
结合判断条件:
if test condition; then
commands
fi
bash shell 提供了另一种 条件测试 方法:
if [ condition ]; then
commands
fi
方括号[ ]
定义了测试条件, 可以把 [ ]
理解为 test
的另一种写法.
注意:
[ ]
这两个方括号, [
后面有一个空格
, ]
前面有一个空格
, 空格
不能丢, 否则会报错!!!
3.1 条件测试: 数值比较
test
命令比较两个整数 n1
和 n2
的大小关系:
整数值比较 | 描述 |
---|---|
n1 -eq n2 | equals 比较, 检查 n1 == n2 是否成立 |
n1 -ge n2 | great equals 比较, 检查 n1 >= n2 是否成立 |
n1 -gt n2 | great than 比较, 检查 n1 > n2 是否成立 |
n1 -le n2 | less equals 比较, 检查 n1 <= n2 是否成立 |
n1 -lt n2 | less than 比较, 检查 n1 < n2 是否成立 |
n1 -ne n2 | not equals 比较, 检查 n1 != n2 是否成立 |
示例:
$ cat temp.sh
#!/bin/bash
value=5
if [ $value -eq 5 ]; then
echo "value == 5 is true"
else
echo "value != 5"
fi
$ ./temp.sh
value == 5 is true
3.2 条件测试: 字符串比较
数值比价时用到都是 -eq
, -ne
这种参数, 字符串比较用到了 =
, !=
, >
和 <
操作符.
test
命令的 字符串比较:
字符串比较 | 描述 |
---|---|
str1 = str2 | 检查 str1 和 str2 是否相同 |
str1 != str2 | 检查 str1 和 str2 是否不同 |
str1 < str2 | 检查 str1 是否比 str2 小, 注: < 需要转义(避免识别为重定向) |
str1 > str2 | 检查 str1 是否比 str2 大, 注: > 需要转义(避免识别为重定向) |
-n str1 | nonzero, 检查 str1 的长度是否 非0 |
-z str1 | 检查 str1 的长度是否为 0 |
字符串比较, 示例:
$ cat temp.sh
#!/bin/bash
user=miyan
if [ $USER = $user ]; then
echo "Welcome ${user} !!!"
else
echo "emmm... hello, $user"
fi
$ ./temp.sh
Welcome miyan !!!
3.3 条件测试: 文件比较
文件比较 是比较测试中很常用的 比较形式.
test
命令的文件比较:
文件比较 | 描述 |
---|---|
-d file | directory, 检查 file 是否存在 并 是一个目录 |
-e file | exist, 检查 file 是否存在 |
-f file | regular file, 检查 file 是否存在 并 是一个文件 |
-r file | readable, 检查 file 是否存在 并 可读 |
-s file | size > 0, 检查 file 是否存在 并 非空 |
-w file | writable, 检查 file 是否存在 并 可写 |
-x file | executable, 检查 file 是否存在 并 可执行 |
-O file | owner, 检查 file 是否存在 并 属于当前用户所有 |
-G file | group, 检查 file 是否存在 并 默认组与当前用户相同 |
file1 -nt file2 | newer than, 检查 file1 是否比 file2 新 |
file1 -ot file2 | older than, 检查 file1 是否比 file2 旧 |
[ ]
文件比较 示例:
$ cat temp.sh
#!/bin/bash
dir=/opt/cherry
# 是否存在 并 是一个目录
if [ -d $dir ]; then
echo "cd $dir"
cd $dir
echo "ls -l "
ls -l
else
echo "$dir does not exist."
fi
$ ./temp.sh
cd /opt/cherry
ls -l
total 36164
-rwxrwxrwx 1 miyan miyan 37010591 Jun 8 18:44 cherry-1.0-SNAPSHOT-fcaf1f7.jar
lrwxrwxrwx 1 jenkins jenkins 43 Jun 8 18:44 cherry-1.0-SNAPSHOT.jar -> /opt/cherry/cherry-1.0-SNAPSHOT-fcaf1f7.jar
-rw-rw-r-- 1 miyan miyan 1987 Apr 20 23:39 cherry.yaml
drwxrwxrwx 2 miyan miyan 4096 Jun 9 14:33 logs
drwxrwxr-x 4 miyan miyan 4096 Apr 21 00:30 node2
drwxrwxr-x 3 miyan miyan 4096 Apr 20 23:38 prod
drwxrwxrwx 2 miyan miyan 4096 Jun 9 14:33 var
4 复合条件测试
复合条件测试 有两种:
and
逻辑:[ condition1 ] && [ condition2 ]
or
逻辑:[ condition1 ] || [ condition2 ]
条件测试 and
复合逻辑 示例:
$ cat temp.sh
#!/bin/bash
value=2
if [ $value -eq 2 ] && [ -w $HOME/test/temp.sh ]; then
echo "writable."
else
echo "not writable."
fi
$ ./temp.sh
writable.
5 if-then 的高级特性
bash shell 为 if-then
语句提供了两个高级特性:
- 双括号
(())
用于 数学运算(逻辑运算, 算数运算, 位运算等) - 双方括号
[[]]
用于 字符串处理.
5.1 双括号(()) 处理数学运算
双括号 ((expression))
允许在 比较过程中使用 高级数学表达式.
((expression))
中 expression 支持以下运算符:
符号 | 描述 |
---|---|
==, !=, >=, >, <=, < | 逻辑运算符 |
val++, val–, ++val, --val | 后增, 后减, 先增, 先减 |
! | 逻辑取反 |
~ | 位取反 |
** | 幂运算 |
<<, >> | 左移位, 右移位 |
&, | | 位布尔和, 位布尔或 |
&&, || | 逻辑和, 逻辑或 |
由上表可知, 使用双括号(())
, 可以使 if-then
几乎像 java语言 一样书写 条件表达式.
双括号((expression))
示例:
$ cat temp.sh
#!/bin/bash
value=2
# 双括号内表达式用到的高级运算符: 大于等于, 逻辑和, 幂运算, 小于
if (($value >= 2 && $value ** 2 < 10)); then
echo "good."
else
echo "bad."
fi
$ ./temp.sh
good.
5.2 双方括号[[]] 处理字符串
双方括号 [[ expression ]]
提供了 模式匹配(pattern matching) 特性.
注意:
双方括号 [[ expression ]]
里面 expression 前后 必须 有两个空格. 这一点和 条件测试 的单方括号 [ expression ]
要求一样.
可以在 模式匹配 中, 使用正则表达式:
$ cat temp.sh
#!/bin/bash
# 我的用户是 miyan
if [[ $USER == m* ]]; then
echo "good."
else
echo "bad."
fi
$ ./temp.sh
good.
6 case 命令
case 命令的用法:
case variable in
pattern1 | pattern2)
commands1;;
pattern3)
commands2;;
*)
default commands;;
esac
可以在 case 的匹配模式中使用 逻辑或(用 |
表示), 也可以使用 通配符(用 *
表示).
case 命令示例:
$ cat temp.sh
#!/bin/bash
case $USER in
vip1 | vip2)
echo "hello vip."
echo "pleasure enjoy your visit.";;
test)
echo "hello test.";;
*)
echo "sorry, you are not allowed here.";;
esac
$ ./temp.sh
sorry, you are not allowed here.
Reference
[1]. Linux命令行与shell脚本编程大全(第三版)