文章目录
1. 条件判断
1.1 条件判断类型
- 整数测试 // 判断大小,是否相等
- 字符测试 // 判断字符串的字母顺序等
- 文件测试 // 是否存在,大小等
1.2 条件测试表达式
[ expression ]
[[ expression ]]
test expression
[root@master ~]# [ 1 -gt 2 ] ## 前后要有空格
[root@master ~]# echo $?
1
[root@master ~]# [[ 1 -gt 2 ]]
[root@master ~]# echo $?
1
[root@master ~]# test 1 -gt 2
[root@master ~]# echo $?
1
# 判断1是否大于2
1.3 整数测试(双目(2个数测试为双目))
-eq //测试两个整数是否相等
-ne //测试两个整数是否不等
-gt //测试一个数是否大于另一个数
-lt //测试一个数是否小于另一个数
-ge //大于或等于
-le //小于或等于
#均为英文单词缩写
1.4 字符测试
== //等值比较,检查==两边的内容是否一致,==两边都要有空格
!= //检查两边内容是否不一致,不一致为真,一致为假
=~ //左侧字符串是否能够被右侧的PATTERN所匹配到。此表达式应用于双中括号[[]]中
-z "string" //测试指定字符串是否为空,空则为真,不空则为假
-n "string" //测试指定字符串是否不空,不空则为真,空则为假
[root@master ~]# [ 'abc1' == 'abc' ]
[root@master ~]# echo $?
1
[root@master ~]# [[ 'abc1' =~ a. ]]
[root@master ~]# echo $?
0
[root@master ~]# [[ 'abc1' =~ 'a.' ]]
[root@master ~]# echo $?
1
[root@master ~]# [[ 'abc1' =~ "a." ]]
[root@master ~]# echo $?
1
[root@master ~]# [ -z "" ]
[root@master ~]# echo $?
0
[root@master ~]# [ -z " " ]
[root@master ~]# echo $?
1
[root@master ~]# a=
[root@master ~]# [ -z $a]
[root@master ~]# echo $?
0
[root@master ~]# a=10
[root@master ~]# [ -z $a ]
[root@master ~]# echo $?
1
[root@master ~]# [[ 'azc' > 'adb' ]]
[root@master ~]# echo $?
0
[root@master ~]# [[ 'azc' > 'acz' ]]
[root@master ~]# echo $?
0
[root@master ~]# [[ 'azc' < 'acz' ]]
[root@master ~]# echo $?
1
[root@master ~]# [[ 'Azc' > 'bzc' ]]
[root@master ~]# echo $?
1
[root@master ~]# [[ 'Azc' > 'azc' ]]
[root@master ~]# echo $?
0
#字母相同时,大写的字母大
#大致按ASCII表来看,
1.5 文件测试
//存在性测试:
-e //测试文件是否存在
//存在性及类别测试:
-b //测试文件是否为块设备文件
-c //测试文件是否为字符设备文件
-f //测试文件是否为普通文件
-d //测试指定路径是否为目录
-h //测试文件是否为符号链接文件
-L //测试文件是否为符号链接文件
-p //测试文件是否为命名管道文件
-S //测试文件是否为套接字文件
//文件权限测试:
-r //测试当前用户对指定文件是否有读权限
-w //测试当前用户对指定文件是否有写权限
-x //测试当前用户对指定文件是否有执行权限
//文件特殊权限测试:
-g //测试文件是否有sgid权限
-u //测试文件是否有suid权限
-k //测试文件是否有sticky权限
//文件大小测试:
-s //测试文件是否非空
//文件是否打开测试:
-t fd //fd表示的文件描述符是否已经打开且与某终端相关
//双目测试:
file1 -ef file2 //测试file1与file2是否指向同一个设备上的相同inode,说白点就是两者是不是同一个文件
file1 -nt file2 //测试file1是否比file2新
file1 -ot file2 //测试file1是否比file2旧
//无分类:
-N //测试文件自从上一次被读取之后是否被修改过
-O //测试文件是否存在并且被当前用户拥有
-G //测试文件是否存在并且默认组是否为当前用户组
[root@master ~]# touch abc
[root@master ~]# [ -e abc ]
[root@master ~]# echo $?
0
[root@master ~]# mkdir ab
[root@master ~]# [ -e ab ]
[root@master ~]# echo $?
0
[root@master ~]# [ -f abc ]
[root@master ~]# echo $?
0
[root@master ~]# [ -f ab ]
[root@master ~]# echo $?
1
1.6 组合测试条件
-a //与关系
-o //或关系
! //非关系
[root@master ~]# [ 1 -gt 2 -a 2 -gt 1 ]
[root@master ~]# echo $?
1
[root@master ~]# [ 1 -lt 2 -a 2 -gt 1 ]
[root@master ~]# echo $?
0
[root@master ~]# [ 1 -gt 2 -o 2 -gt 1 ]
[root@master ~]# echo $?
0
[root@master ~]# [ 1 -lt 2 ] && [ 2 -gt 1 ]
[root@master ~]# echo $?
0
1.7 条件判断,控制结构
1.7.1 单分支if语句
if 判断条件; then
statement1
statement2
......
fi
[root@master ~]# bash useradd.sh tom
[root@master ~]# id tom
uid=1001(tom) gid=1001(tom) 组=1001(tom)
[root@master ~]# bash useradd.sh tom
[root@master ~]# cat useradd.sh
#!/bin/bash
id $1 &> /dev/null #不显示输出
if [ $? -ne 0 ];then
useradd $1
fi
1.7.2 双分支if语句
if 判断条件; then
statement1
statement2
......
else
statement3
statement4
......
fi
1.7.3 多分支if语句
if 判断条件1; then
statement1
statement2
......
elif 判断条件2; then
statement3
statement4
......
else
statement5
statement6
......
fi
[root@master ~]# ./test.sh 2
>1
[root@master ~]# ./test.sh 1
=1
[root@master ~]# ./test.sh 0
<1
[root@master ~]# cat test.sh
#!/bin/bash
if [ $1 -gt 1 ];then
echo '>1'
elif [ $1 -lt 1 ];then
echo '<1'
else
echo '=1'
fi
#与python类似
也可以使用逻辑运算符实现
condition && action //如果condition为真则执行action
condition || action //如果condition为假则执行action
[root@localhost ~]# touch 123
[root@localhost ~]# ls
123 anaconda-ks.cfg
[root@localhost ~]# mkdir 123
mkdir: 无法创建目录"123": 文件已存在
[root@localhost ~]# mkdir 123 || rm -f 123
mkdir: 无法创建目录"123": 文件已存在
[root@localhost ~]# ls
anaconda-ks.cfg logs
[root@localhost ~]# mkdir 123 && touch 123/456
[root@localhost ~]# ls 123
456
2. 模式匹配:case
case $变量名 in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
//case支持glob风格的通配符:
* //任意长度任意字符
? //任意单个字符
[] //指字范围内的任意单个字符
abc|bcd //abc或bcd
[root@master ~]# ./case.sh 1
you input 1
[root@master ~]# ./case.sh 2
you input 2
[root@master ~]# ./case.sh 3
you input 3
[root@master ~]# ./case.sh 6
errro
[root@master ~]# cat case.sh
#!/bin/bash
case $1 in
1)
echo 'you input 1'
;;
2)
echo 'you input 2'
;;
3)
echo 'you input 3'
;;
*)
echo ' errro'
;;
esac
3. 循环语句
shell中有3种循环语句
- for
- while
- until
循环语句通常需要有一个进入条件和一个退出条件。
死循环只有进入条件
3.1 for循环
for循环当列表不为空时进入循环,否则退出循环
for 变量 in 列表; do
循环体
done
for ((expr1;expr2;expr3))
{
循环体
}
for (( expr1 ; expr2 ; expr3 ));do
循环体
done
expr1 //用于指定初始条件,给控制变量一个初始值
expr2 //判定什么时候退出循环
expr3 //修正expr1指定的变量的值
//如何生成列表:
{1..100}
seq [起始数] [步进长度] 结束数
[root@master tmp]# ./for.sh
=====================
sshd:x:74:74:Privilege-separated
=====================
SSH:/var/empty/sshd:/sbin/nologin
=====================
avahi:x:70:70:Avahi
=====================
mDNS/DNS-SD
=====================
Stack:/var/run/avahi-daemon:/sbin/nologin
=====================
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
=====================
tcpdump:x:72:72::/:/sbin/nologin
=====================
l:x:1000:1000:l:/home/l:/bin/bash
=====================
mysql:x:988:982::/home/mysql:/sbin/nologin
=====================
tom:x:1001:1001::/home/tom:/bin/bash
=====================
[root@master tmp]# cat for.sh
#!/bin/bash
echo =====================
for line in $(cat /tmp/passwd);do
echo $line
echo =====================
done
也可以
[root@master tmp]# ./for.sh
=====================
sshd:
=====================
SSH:
=====================
avahi:
=====================
mDNS/DNS-SD:
=====================
Stack:
=====================
postfix: /sbin/nologin
=====================
tcpdump: /sbin/nologin
=====================
l: /bin/bash
=====================
mysql: /sbin/nologin
=====================
tom: /bin/bash
=====================
[root@master tmp]# cat for.sh
#!/bin/bash
echo =====================
for line in $(cat /tmp/passwd);do
echo $line | awk -F: '{print $1": "$7}'
echo =====================
done
[root@master ~]# ./for1.sh
1
2
3
4
5
6
7
8
9
10
[root@master ~]# cat for1.sh
#!/bin/bash
for ((i=1;i<=10;i++))
{
echo $i
}
等同于
[root@master ~]# ./for1.sh
1
2
3
4
5
6
7
8
9
10
[root@master ~]# cat for1.sh
#!/bin/bash
for i in {1..10};do
echo $i
done
还可以
[root@master ~]# ./for1.sh
1
2
3
4
5
6
7
8
9
10
[root@master ~]# cat for1.sh
#!/bin/bash
for i in $(seq 10);do
echo $i
done
批量创建用户
[root@master ~]# ./for1.sh
useradd:用户“user1”已存在
user1 创建成功。
useradd:用户“user2”已存在
user2 创建成功。
useradd:用户“user3”已存在
user3 创建成功。
useradd:用户“user4”已存在
user4 创建成功。
useradd:用户“user5”已存在
user5 创建成功。
useradd:用户“user6”已存在
user6 创建成功。
useradd:用户“user7”已存在
user7 创建成功。
useradd:用户“user8”已存在
user8 创建成功。
useradd:用户“user9”已存在
user9 创建成功。
useradd:用户“user10”已存在
user10 创建成功。
[root@master ~]# cat for1.sh
#!/bin/bash
for ((i=1;i<=10;i++));do
useradd user$i
id user$i &>/dev/null
if [ $? -eq 0 ];then
echo " user$i 创建成功。"
fi
done
批量删除
[root@master ~]# ./for1.sh
user1 删除成功。
user2 删除成功。
user3 删除成功。
user4 删除成功。
user5 删除成功。
user6 删除成功。
user7 删除成功。
user8 删除成功。
user9 删除成功。
user10 删除成功。
[root@master ~]# cat for1.sh
#!/bin/bash
for ((i=1;i<=10;i++));do
userdel -r user$i
id user$i &> /dev/null
if [ $? -ne 0 ];then
echo " user$i 删除成功。"
fi
done
3.2 while循环
while循环适用于循环次数未知的场景,注意要有退出条件。
条件满足时进入循环,条件不满足则退出循环。
while 条件; do
statement //语句
...
done
[root@localhost ~]# cat test.sh
#!/bin/bash
i=10
while [ $i -le 10 -a $i -ge 1 ];do
echo $i
let i-=1
done
[root@localhost ~]# bash test.sh
10
9
8
7
6
5
4
3
2
1
也可以写为
[root@localhost ~]# cat test.sh
#!/bin/bash
i=10
while [ $i -gt 0 ];do
echo $i
let i--
done
3.2.2 while循环特殊用法
//while循环特殊用法一:死循环
while :;do
statement
...
done
//这里的冒号可以改成任何非空值
while循环特殊用法二:逐行读取某文件,将值存入line变量中
while read line;do
statement
...
done < /path/to/somefile
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
-----------------------
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
-----------------------
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
-----------------------
tcpdump:x:72:72::/:/sbin/nologin
-----------------------
l:x:1000:1000:l:/home/l:/bin/bash
-----------------------
nginx:x:988:982::/home/nginx:/sbin/nologin
-----------------------
[root@localhost ~]# cat line.sh
#!/bin/bash
while read line;do
echo $line
echo -----------------------
done < /etc/passwd
可以对取出的行做处理
gnome-initial-setup 989
-----------------------
sshd 74
-----------------------
avahi 70
-----------------------
postfix 89
-----------------------
tcpdump 72
-----------------------
l 1000
-----------------------
nginx 988
-----------------------
[root@localhost ~]# cat line.sh
#!/bin/bash
while read line;do
echo $line | awk -F: '{print $1 ,$3}'
echo -----------------------
done < /etc/passwd
3.3 until循环
条件不满足时进入循环,条件满足退出循环。
until 条件; do
statement
...
done
3.4 循环语句特殊情况
在循环语句中,有几种特别情况:
break [num]:提前退出循环。当循环语句中出现break时,将提前退出循环,不再执行循环后面的语句
continue [num]:提前结束本轮循环而进入下一轮循环。当循环语句执行到continue时,continue后面的语句将不再执行,提前进入下一轮循环
4. 函数
在shell 中有两种定义函数的语法格式,分别为:
函数名()
{
命令
}
或者:
function 函数名()
{
命令
}
[root@localhost ~]# ./lxmp.sh
123
[root@localhost ~]# cat lxmp.sh
#!/bin/bash
hanshu () { //定义函数
echo 123
}
hanshu //使用函数
[root@localhost ~]# ./lxmp.sh
4567
[root@localhost ~]# cat lxmp.sh
#!/bin/bash
function abc () {
echo 4567
}
abc
//函数名字的定义有一定要求,例如不能用纯数字,要与变量区别开等
5. 定义脚本退出状态码
//exit命令用于自 定义执行状态结果
exit # //此处的#号是一个数字,其范围可以是0-255
如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止
在通配符中*可以匹配任意的0个或多个字符,而在正则表达式中他是重复之前的一个或者多个字符