条件测试语句 {#条件测试语句}
基本语法 {#基本语法}
(1) test <条件>
(2) [ <条件> ]
需要注意环境前后要有空格
结果:条件非空的话为 True (真),反之为 False (假)
需要注意,在Shell中,通常情况下0为真,其他数值为假(特殊情况如字符串测试等除外)。
|-----------|-----------------------------|
| 1
| test homo ; echo $?
|
文件测试 {#文件测试}
配合操作符,可以实现文件或者目录类型的检测。
例如,检测当前路径下的 homo 是不是目录?
|---------------|------------------------------------------------------------------|
| 1 2 3
| touch homo test -d homo ; echo $? #或使用[ -d homo];echo $?
|
以下是文件测试操作符与相应说明的对应关系
| 操作符 | 说明 | |:-------:|:-------------------:| | -d | 测试是否为目录(Directory) | | -a | 测试目录或文件是否存在(Exist) | | -f | 测试是否为文件(File) | | -r | 测试当前用户是否可读(read) | | -w | 测试当前用户是否可写(write) | | -x | 测试当前用户是否可执行(excute) |
整数测试 {#整数测试}
整数测试通常用于数值之间的运算,在一些逻辑关系的判断中有应用。
例如判断 1+1+5+4 与 1+9+1 是否相等,可以这么写
|-------------|------------------------------------------------------------------|
| 1 2
| echo $(( 1 + 1 + 5 + 4 )) -eq $(( 1 + 9 + 1 )) ; echo $?
|
以下是关系测试操作符与相应说明的对应关系
| 操作符 | 关系运算符 | 说明 | |:---:|:-----:|:-----------------------:| | -eq | == | 等于(Equal) | | -ne | != | 不等于(Not Equal) | | -gt | > | 大于(Greater Than) | | -lt | < | 小于(Lesser Than) | | -le | <= | 小于或等于(Lesser or Equal) | | -ge | >= | 大于或等于(Greater or Equal) |
字符串测试 {#字符串测试}
字符串测试操作符的作用包括比较字符串是否相同、测试字符串的长度是否为0。
格式为: [字符串1] 操作符 [字符串2]
以下是字符串测试操作符与相应说明的对应关系
| 操作符 | 含义 | |:---:|:-----------------:| | -z | 判断字符串长度是否为 0 | | -n | 判断字符串长度是否为 非0 | | ! | 判断两边字符串是否 不相等 | | = | 判断两边字符串是否 相等 |
逻辑运算符 {#逻辑运算符}
在Shell条件测试中,使用逻辑运算符实现复杂的条件测试,逻辑运算符用于操作两个变量。
格式为: [表达式1] 操作符 [表达式2]
注意: -a
和 -o
放在 [ ]
里面用, &&
和 ||
放在 [ ]
外面用
以下是逻辑运算操作符与相应说明的对应关系
| 操作符 | 含义 | |:---------:|:--:| | -a 或 && | 与 | | -o 或 || | 或 | | ! | 否 |
if条件 {#if条件}
很常见的判断语句,不过要注意Shell中的流程控制不能为空
即如果 else
分支没有语句执行,就不需要写
if单分支 {#if单分支}
|---------------|---------------------------------|
| 1 2 3
| if [条件表达式]; then 代码块 fi
|
if双分支 {#if双分支}
|---------------------|-------------------------------------------|
| 1 2 3 4 5 6
| if [条件表达式] then 代码块1 else 代码块2 fi
|
if多分支 {#if多分支}
|---------------------------|-----------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9
| if [条件表达式1]; then 代码块1 elif [条件表达式2]; then 代码块2 elif [条件表达式3]; then 代码块3 else 代码块4 fi
|
case条件 {#case条件}
程序会获取case语句中的 变量值
-
如果满足条件表达式1,则执行代码块 1
-
如果满足条件表达式2,则执行代码块2
-
如果满足条件表达式3,则执行代码块3
-
执行到双分号
;;
,则停止 -
如果都不满足,则执行
*)
后面的代码块(上面的双分号会被忽略)只要满足一个条件表达式就会跳出
case
语句主体,执行esac
字符后面的命令
|---------------------------------------|-------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13
| case 变量值 in 条件表达式1) 代码块1 ;; 条件表达式2) 代码块2 ;; 条件表达式3) 代码块3 ;; *) 无匹配后代码块 esac
|
条件表达式的匹配符如下表所示
| 条件表达式 | 说明 | |:---------:|:---------:| | * | 任意字符 | | ? | 任意单个字符 | | [abc] | a、b或c其中之一 | | [a-n] | 从a到n的任一字符 | | | | 多重选择 |
for循环 {#for循环}
语法 {#语法}
当变量值在列表时, for
循环即执行一次所有命令,使用变量名获取列表中的当前取值
in
的取值列表支持替换、字符串和文件名;不用取值列表将使用命令行的位置参数
通常写法
|-----------------|-------------------------------------------|
| 1 2 3 4
| for [变量名] in [取值列表] do [循环体] done
|
一行写法
|-----------|---------------------------------------------|
| 1
| for [变量名] in [取值列表]; do [循环体] done;
|
💡提醒:写成一行(在终端直接执行)时,需要记得加 ;
符号。
例子 {#例子}
脚本将读取用户清单文件(格式: [用户名] [密码]
),并对文件的文本内容进行切片处理(例如第一个参数为用户名,第二个参数为密码),据此创建用户并配置好密码。
|---------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #!/bin/bash #IFS是内部字段分隔符,此处单词间隔 IFS=$ '\n' #判断脚本是否有参 if [ $# -eq 0 ]; then echo "使用方法: ` $0 ` 用户名单文件" exit 0 fi #判断用户名单是否为文件 if [ ! -f $1 ]; then echo "错误:用户名单 $1 不是文件" exit 0 fi #批量创建用户并设置密码 for line in ` cat $1 ` do if [ ${#line} -eq 0 ]; then #获取文本的长度 echo "清单出现空行,跳过创建。" continue fi #从用户名单中切割出用户名 user=` echo " ${line} " | awk '{print $1}' ` #从用户名单中切割出用户密码 pass=` echo " ${line} " | awk '{print $2}' ` #查询用户是否存在 id ${user} &> /dev/null #根据存在与否创建用户并设置密码 if [ $? -eq 0 ]; then echo "提示:用户 ${user} 已经存在!" else #创建用户 useradd ${user} echo "用户 ${user} 已创建完毕!" #通过管道服务为用户设置密码 echo " ${pass} | passwd -stdin ${user} &> /dev/null" if [ $? -eq 0 ]; then echo "用户 ${user} 的密码配置完毕!" fi fi done echo "提示:已通过文件 $1 的用户清单创建用户,并配置密码。"
|
while循环 {#while循环}
用于不断执行一系列命令,也用于从输入文件中读取数据
语法 {#语法-1}
常规写法
|-----------------|-------------------------------------|
| 1 2 3 4
| while [条件表达式] do [代码块] done
|
无限循环
|-----------------|-----------------------------------------------|
| 1 2 3 4
| while : #也可写成while true do [循环体] done
|
例子 {#例子-1}
|-------------------------|------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8
| # !/bin/bash # 读取键盘信息 echo "按下 Crtl和D 退出" echo -n '你想吃啥: ' while read FOOD do echo "老板,来份:${FOOD}~" done
|
until循环 {#until循环}
与while循环相反,until 循环则默认执行,直到条件满足 true
时停止
语法 {#语法-2}
如果条件表达式的返回值为 false,则继续执行循环体内的语句,否则跳出循环。
|-----------------|-------------------------------------|
| 1 2 3 4
| until [条件表达式] do [循环体] done
|
例子 {#例子-2}
|-------------------------|----------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8
| # !/bin/bash # 遍历输出0-9 a=0 until [ ! $a -lt 10 ] do echo ${a} a=$[${a}+1] done
|
跳出循环 {#跳出循环}
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环。 break
允许跳出所有循环,而 continue
仅跳出当前循环。