条件测试
测试格式:
格式一: test 条件表达式
格式二: [ 条件表达式 ] #注意前后空格
两种方式作用相同,后一种形式更为常用。 执行条件测试操作后,通过预定义变量“$?”可以获得测试命令的返回状态值,条件成立,为0,否则为1
文件测试
常用的文件测试操作符:
| 操作符 | 作用 |
|---|---|
| -d | 测试文件是否为目录文件(Directory) |
| -f | 测试文件是否为普通文件(File) |
| -e | 测试目录或文件是否存在(Exist)。建议使用-e,-a可能不准确。 |
| -a | 测试目录或文件是否存在(Exist) |
| -r | 测试当前用户是否有权限读取(Read) |
| -w | 测试当前用户是否有权限写入(Write) |
| -x | 测试当前用户是否有权限执行(eXcute) |
| -L | 测试是否为符号链接(软链接文件) |
| -nt | 判断文件A是否比文件B新 |
| -ot | 判断文件A是否比文件B旧 |
| -ef | 判断两个文件是否为同一文件。可用于硬链接,主要判断两个文件是否指向同一个inode。 |
属性测试补充:
| 操作符 | 作用 |
|---|---|
| -s FILE | 判断文件是否存在且非空 |
| -t fd | fd 指定文件描述符是否在某终端已经打开 |
| -N FILE | 文件自从上一次被读取之后是否被修改过 |
| -O FILE | 当前有效用户是否为文件属主 |
| -G FILE | 当前有效用户是否为文件属组 |
[root@localhost ~]#ll /etc/shadow
---------- 1 root root 1549 10月 19 10:58 /etc/shadow
[root@localhost ~]#[ -r /etc/shadow ]
[root@localhost ~]#echo $?
0
#实际效果,不是表面显示,注意root权限
[root@localhost ~]#[ -x /etc/shadow ]
[root@localhost ~]#echo $?
1
root执行权限别人没有root也没有,别人有root也有
整数值比较
| 操作符 | 含义 |
|---|---|
| -eq | 等于(Equal) |
| -ne | 不等于(Not Equal) |
| -gt | 大于(Greater Than) |
| -lt | 小于(Lesser Than) |
| -le | 小于或等于(Lesser or Equal) |
| -ge | 大于或等于(Greater or Equal) |
字符串比较
常用的测试操作符
- =:字符串内容相同
- !=:字符串内容不同,! 号表示相反的意思
- -z:字符串内容为空
- -n:字符是否存在
字符串比较,常用的四种格式:
[ "字符串1" = "字符串2" ] //测试字符串1和字符串2的内容是否相同
[ "字符串1" != "字符串2” ] //测试字符串1和字符串2的内容是否不同
[ -z "字符串" ] //测试字符串是否为空,或者指定的变量是否为空值。(测试字符串的长度是否为零)
[ -n "字符串" ] //测试字符串是否存在,即是否不为空。(测试字符串的长度是否非零)
逻辑测试
逻辑运算符:
- -a或&& :逻辑与,“而且”的意思,全真才为真。
- -o或|| :逻辑或,“或者”的意思,一真即为真。
- ! :逻辑否。
1)短路与 &&
CMD1 && CMD2
全真才为真,一假即为假。
第一个CMD1结果为真 ,第二个CMD2必须要参与运算,才能得到最终的结果。
第一个CMD1结果为假 ,总的结果必定为假,因此不需要执行CMD2。
同时满足命令1 和命令2 的要求,才会返回正确。
2)短路或 ||
CMD1 || CMD2
一真即为真
第一个CMD1结果为真,总的结果必定为真,因此不需要执行CMD2。
第一个CMD1结果为假,第二个CMD2必须要参与运算,才能得到最终的结果。
3)三元运算符
[ 表达式 ] && a || b
当表达式为真时,取a值;当表达式为假时,取b值。
[表达式1] && [表达式2] 等同于 [表达式1 -a 表达式2] 等同于 [[表达式1 && 表达式2]]
[表达式1] || [表达式2] 等同于 [表达式1 -o 表达式2] 等同于 [[表达式1 || 表达式2]]
() {}
(CMD1;CMD2;...)和 {空格CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行
#()会开启子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#( echo $BASHPID;sleep 100)
1979
#{ } 不会开启子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#{ echo $BASHPID; }
1920
[root@localhost data]#name=lc
[root@localhost data]#( name=mcl;echo $name );echo $name
mcl
lc
[root@localhost data]#name=lc
[root@localhost data]#{ name=mcl;echo $name; };echo $name
mcl
mcl
if语句的结构
单分支
if 判断条件;
then
条件为真的分支代码
fi
双分支
if 判断条件;
then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支
if 判断条件1
then
条件1为真的分支代码
elif 判断条件2
then
条件2为真的分支代码
elif 判断条件3;then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fi
case分支语句
格式:
case 变量引用 in
模式1)
命令分支1
;;
模式2)
命令分支2
;;
...
*)
默认命令分支
esac
echo命令
echo -n 表示不换行输出
echo -e 表示输出转义符
常用的转义符
| 选项 | 作用 |
|---|---|
| \r | 光标移至行首,并且不换行 |
| \s | 当前shell的名称,如bash |
\t | 插入Tab键,制表符 |
\n | 输出换行 |
| \f | 换行,但光标仍停留在原处 |
| \ | 表示插入"\"本身转义 |
\b | 表示退格 不显示前一个字符 |
\c | 抑制更多的输出或不换行 |
[root@localhost ky15]#echo -e "12345\b\b\b\b678"
16785
###注意退格键和末尾的字符相关,超过末尾的字符数量 会出bug 了解即可
[root@localhost ky15]#echo -e "1234\c5678"
1234[root@localhost ky15]#
###\c 注意 使用在数字中间会把后面内容删除
echo -e "n\n\n\n\n\nw"|fdisk /dev/sdb
#自动硬盘分区
[root@localhost data]#rm -rf 123
#是把软连接删除
[root@localhost data]#rm -rr 123/
#把软连接里的文件全删除
循环语句
for循环
用法:
- 读取不同的变量值,用来逐个执行同一组命令。
- 使用场景:一般用于循环次数事先已知的场景。
- 执行机制:遍历。
格式:
for 变量名 in 取值列表
do
命令序列
done
for的三个默认分隔符
环境变量$IFS,是指内部字段分隔符, 默认为三个:空格、制表符 \t、换行符 \n。
若使用for读取文件内容,文件中有空格 在脚本中,先临时将变量IFS的值中的空格删除,使for语句不以空格作为分隔符,最后还原变量值。
[root@yuji sh]# vim fen2.sh //写脚本
#!/bin/bash
#借用一个临时变量先保存IFS的原始值
IFS_OLD=$IFS
#删除空格和制表符,只保留换行符作为分隔符
IFS=$'\n'
#从文件中获取变量值,$()表示调用命令执行的结果
for name in $(cat name.txt)
do
echo "$name"
done
#还原变量IFS的原始值
IFS=$IFS_OLD
[root@yuji sh]# cat name.txt //查看文件内容,只有3行
zhang san
lisi
wang wu
[root@yuji sh]# bash fen2.sh //运行脚本,显示3行
zhang san
lisi
wang wu
while
相对于for,需要知道循环次数
我们只知道停止条件,不知道次数,就需要使用while
直到达到条件
格式:
while 条件测试操作
do
命令序列
done
until
用法:
- 重复测试某个条件,只要条件不成立则反复执行。
格式:
until 条件测试操作
do
命令序列
done
continue
continue的作用:
-
终止某次循环的执行,本次循环continue后面的语句不会执行,但不会完全终止整个循环。就是直接跳过满足条件的循环,即满足条件的不执行。
-
continue一般用于for循环。在while和until中要慎用,因为如果变量迭代语句放在continue之后,那么迭代不会执行,会造成死循环。
break
break的作用:
- 跳出单层循环,默认为break 1,后面的数字为跳出层数。例如"break 2"为跳出2层循环。
- 循环内break之后的语句都不会执行,但循环外的语句仍然会执行。4