语句结构
for 变量名 in 取值列表
do
命令序列
done
语句结构举例
for 收件人 in 邮件地址列表
do
发送邮件
done
示例1
[root@localhost opt]# vim user.txt
zhangsan
lisi
wangermazi
zhaoliu
tianji
wangba
[root@localhost opt]# vim useradd.sh
#!/bin/bash
Lists=$(cat /opt/user.txt)
for bb in $Lists
do
useradd $bb
echo "19961207" | passwd --stdin $bb
echo "$bb添加成功"
done
[root@localhost opt]# chmod +x useradd.sh
[root@localhost opt]# ./useradd.sh
Changing password for user zhangsan.
passwd: all authentication tokens updated successfully.
zhangsan添加成功
......
批量删除用户:在刚刚的基础上修改
[root@localhost opt]# vim useradd.sh
#!/bin/bash
Lists=$(cat /opt/user.txt)
for bb in $Lists
do
userdel -r $bb '-r 删除家目录'
#echo "123456" | passwd --stdin $bb &> /dev/null
echo "$bb删除成功"
done
[root@localhost opt]# ./useradd.sh
zhangsan删除成功
lisi删除成功
wangermazi删除成功
zhaoliu删除成功
tianji删除成功
wangba删除成功
[root@localhost opt]# cat /etc/passwd | grep "bash"
root:x:0:0:root:/root:/bin/bash
dd:x:1000:1000:cn-tangzheng:/home/cn-tangzheng:/bin/bash
示例2
[root@localhost opt]# vim ipcheck.sh
#!/bin/bash
List=$(cat /opt/ipadds.txt)
for IP in $List
do
ping -c 3 -i 0.2 -W 3 $IP > /dev/null
if [ $? -eq 0 ];then
echo "${IP} is up"
else
echo "${IP} is down"
fi
done
[root@localhost opt]# sh ipcheck.sh
192.168.100.100 is down
192.168.1.112 is up
14.0.0.14 is up
示例三:
法一:
#!/bin/bash
for ((i=1;i<=10;i++))
do
echo "$i"
done
法二:
#!/bin/bash
i=1
for ((;i<=10;i++))
do
echo "$i"
done
法三:
#!/bin/bash
i=1
for ((;i<=10;))
do
echo "$i"
let i++
done
法四:
#!/bin/bash
i=1
for ((;;))
do
if [ $i -le 10 ]
then
echo "$i"
let i++
else
exit 0
fi
done
运行结果:
[root@localhost opt]# ./number.sh
1
2
3
4
5
6
7
8
9
10
let 对整数进行数学运算
let和双小括号 (( )) 一样,let 命令也只能进行整数运算,不能对小数(浮点数)或者字符串进行运算。
语法格式
let 表达式
或
let "表达式"
或
let '表达式'
以上方式都等价于 ((表达式))
当表达式中含有 Shell 特殊字符(例如 |)时,需要用双引号" "或者单引号’ '将表达式包围起来。
和 (( )) 类似,let 命令也支持一次性计算多个表达式,并且以最后一个表达式的值作为整个 let 命令的执行结果
语句结构
while 条件测试操作
do
命令序列
done
语句结构示例
while 未猜中正确的价格
do
反复猜测商品价格
done
示例1
[root@localhost opt]# cat bunengchu3.sh
#!/bin/bash
i=1
while [ $i -lt 100 ]
do
if [ `expr $i % 3` -ne 0 ];then
echo $i
fi
let i++
done
[root@localhost opt]# sh bunengchu3.sh
1
2
4
5
7
8
10
11
13
14
16
17
19
20
22
23
25
26
28
29
31
32
34
35
37
38
40
41
43
44
46
47
49
50
52
53
55
56
58
59
61
62
64
65
67
68
70
71
73
74
76
77
79
80
82
83
85
86
88
89
91
92
94
95
97
98
示例2
#!/bin/bash
while true
do
read -p "请输入yes退出:" KEY
if [ $KEY = yes ]
then
break
fi
done
echo "正常退出"
[root@localhost opt]# ./sixunhuan.sh
请输入yes退出:no
请输入yes退出:1
请输入yes退出:d
请输入yes退出:!
请输入yes退出:a
请输入yes退出:yes
正常退出
示例3
通过变量RANDOM获得随机数
提示用户猜测并记录次数,猜中后退出循环
#!/bin/bash
A=`expr $RANDOM % 1000`
i=0
echo "商品的实际价格为0-999之间,猜猜看是多少?"
read -p "请输入你猜测的价格数目:" num
while [ $num -le 999 ] && [ $num -ge 1 ]
do
let i++
if [ $num -eq $A ]
then
echo "恭喜你答对了,实际价格是$A"
echo "你一共猜测了$i 次"
exit 0
elif [ $num -lt $A ]
then
echo "太低了"
read -p "请输入你猜测的价格数目:" num
else
echo "太高了"
read -p "请输入你猜测的价格数目:" num
fi
done
continue
命令格式
continue n
n 表示循环的层数:
如果省略 n,则表示 continue 只对当前层次的循环语句有效,遇到 continue 会跳过本次循环,忽略本次循环的剩余代码,直接进入下一次循环。
如果带上 n,比如 n 的值为 2,那么 continue 对内层和外层循环语句都有效,不但内层会跳过本次循环,外层也会跳过本次循环,其效果相当于内层循环和外层循环同时执行了不带 n 的 continue。这么说可能有点难以理解,稍后我们通过代码来演示。
continue 关键字也通常和 if 语句一起使用,即满足条件时便跳出循环。
命令格式
break n
n 表示跳出循环的层数,如果省略 n,则表示跳出当前的整个循环。
break 关键字通常和 if 语句一起使用,即满足条件时便跳出循环。
until 条件测试操作
do
命令序列
done
while 未超过10
do
数字依次增加
done
计算1–50的和
通过循环累加的方式计算1–50的和
#!/bin/bash
i=1
sum=0
until [ $i -eq 51 ]
do
echo "$i"
let sum+=$i
let i++
done
echo "和:$sum"
[root@localhost opt]# ./jisuan.sh
1275
示例2
为指定用户发送在线消息
用户名与消息通过为止参数传递给脚本
条件:
1、位置参数个数大于1
2、姓名属于系统用户 /etc/passwd
3、用户是否在线 until who
4、发送消息 echo ”消息“ | write 用户名
[root@localhost opt]# vim usertalk.sh
#!/bin/bash
username=$1
#格式参数不能为空
if [ $# -lt 1 ];then
echo "Usage:`basename $0` []"
exit 1 #异常退出
fi
#验证是否属于系统用户
if grep "^$username" /etc/passwd > /dev/null;then :
#后面加冒号就可以不用>接着写了
else
echo "no user"
exit 2
fi
#测试用户是否在线,如果不在线,每5s联系一次
until who | grep "$username" > /dev/null;do
echo "user not login"
sleep 5
done
#发送消息
echo "$2" | write "$username"
echo "${username}发送成功"
[function] fun_name () {
命令序列
[retrun n] ########返回的是状态码
[echo n] ######返回的是值
}
fun_name #########调用函数
其中,return返回的是状态码,需要使用$?调取
echo 返回的是值,使用变量调用
传参:指位置变量
可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
函数名 [参数1] [参数2]
示例1
两个数字求和
[root@localhost opt]# vim hanshu1.sh
#!/bin/bash
function sum(){
read -p "请输入加数:" num1
read -p "请输入被加数:" num2
sum=$(expr $num1 + $num2)
[return abc] #####中括号表示可有可无
[echo $sum]
}
sum
#函数返回值在调用该函数后通过 $? 来获得
echo "返回值是:$?"
echo "和是:$sum"
[root@localhost opt]# sh hanshu1.sh
请输入加数:45
请输入被加数:54
hanshu1.sh: 第 6 行:return: abc: 需要数字参数
返回值是:255 ####说明返回值是错的
和是:99
由于shell状态码最大是255,所以当返回值大于255时会出错
示例2
[root@localhost ~]# vim .bashrc (局部声明)
[root@localhost ~]# source .bashrc (更新)
[root@localhost ~]# vim /etc/profile
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}
[root@localhost ~]# source /etc/profile
两个环境变量:
.bashrc 用户环境变量文件
/etc/profile 系统环境变量
[root@localhost ~]# vim fun_scope.sh
myfun ()
{
local i i=8 echo $i
}
i=9 myfun echo $i
[root@localhost ~]# chmod +x fun_scope.sh
[root@localhost ~]# ./fun_scope.sh
8
9
参数的用法
函数名称 参数 1 参数 2 参数 3 ......
参数的表示方法
$1、$2、$3…… ${10} ${11}
调用自己本身的函数
示例
[root@localhost opt]# vim digui.sh
#!/bin/bash
function list_files(){
for f in `ls $1`
do
#判断是否为目录
if [ -d "$1/$f" ]
then
echo "$2$f"
#递归调用
list_files "$1/$f" " $2" ##递归自己调自己,又变成$1了
else
echo "$2$f"
fi
done
}
list_files "/var/log" ""
[root@localhost opt]# sh digui.sh
anaconda
anaconda.log
ifcfg.log
journal.log
ks-script-MdTpNR.log
packaging.log
program.log
storage.log
syslog
X.log
audit
audit.log
boot.log
boot.log-20200716
boot.log-20200719
boot.log-20200720
btmp
chrony
cron
cron-20200719
cups
access_log
access_log-20200719
error_log
page_log
dmesg
dmesg.old
firewalld
gdm
:0-greeter.log
:0-greeter.log.1
:0-greeter.log.2
:0-greeter.log.3
:0-greeter.log.4
:0.log
:0.log.1
:0.log.2
:0.log.3
:0.log.4
:1-greeter.log
:1.log
glusterfs
grubby_prune_debug
lastlog
libvirt
qemu
maillog
maillog-20200719
messages
messages-20200719
ntpstats
pluto
peer
ppp
qemu-ga
rhsm
sa
sa15
sa16
sa17
sa18
sa19
sa20
sar16
sar17
sar18
sar19
samba
old
secure
secure-20200719
speech-dispatcher
spooler
spooler-20200719
sssd
swtpm
libvirt
qemu
tallylog
tuned
tuned.log
vmware-network.1.log
vmware-network.2.log
vmware-network.3.log
vmware-network.4.log
vmware-network.5.log
vmware-network.6.log
vmware-network.log
vmware-vgauthsvc.log.0
vmware-vmsvc.log
vmware-vmusr.log
wpa_supplicant.log
wtmp
xferlog
Xorg.0.log
Xorg.0.log.old
Xorg.1.log
Xorg.9.log
yum.log
数组名=(value0 value1 value2 …)
[root@localhost opt]# num=(11 22 33 44)
[root@localhost opt]# echo $num ###这样调不出来
11
[root@localhost opt]# echo ${num[*]} ###*代表全部,[]代表元素的下标
11 22 33 44
[root@localhost opt]# echo ${num[2]}
33
数组名=([0]=value [1]=value [2]=value …)
[root@localhost opt]# num=([0]=55 [1]=66 [2]=77 [3]=88)
[root@localhost opt]# echo ${num[@]} ########@和*都表示所有
55 66 77 88
[root@localhost opt]# echo ${num[*]}
55 66 77 88
列表名=”value0 value1 value2 …”
数组名=($列表名)
[root@localhost opt]# list="11 12 13 14" ####先定义列表,列表再赋值给数组
[root@localhost opt]# num=($list)
[root@localhost opt]# echo ${num[*]}
11 12 13 14
数组名[0]=”value” 数组名[1]=”value” 数组名[2]=”value”
方法四一般用来作替换,替换掉某一个元素
[root@localhost opt]# echo ${num[*]}
11 12 13 14
[root@localhost opt]# num[1]=88
[root@localhost opt]# echo ${num[*]}
11 88 13 14
如:[11,22,33,44] 在内存中开辟了连续的空间
配合着循环使用
数组名称:arr arr=(11,22,33,44) 索引
数组元素:如11 0 1 2 3
数组长度 :4 (元素的个数)
数组下标:33元素的下标值是2
需求:创建一个1-100的数组
[root@localhost opt]# vim arr.sh
#!/bin/bash
for ((i=0;i<=99;i++));do
arr[$i]=$[$i+1]
done
echo ${arr[*]}
创建存放(1-100)奇数的数组:
分析:
下标 元素 增量
0 1 1
1 3 2
2 5 3
3 7 4
$i $k $j
k=$i+$j
[root@localhost opt]# vim arr02.sh
#!/bin/bash
#创建存放(1-100)奇数的数组
k=0 #元素
j=1 #增量
for ((i=0;i<=99;i++))
do
k=$[$i+$j]
let j++
#最大元素不能超过100
if [ $k -le 100 ]
then
arr[$i]=$k
fi
done
echo ${arr[*]}
[root@localhost opt]# sh arr02.sh
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
创建任意数字及长度的数组,根据客户需求加入元素:
分析:
利用好死循环和break
while 条件始终成立
do
if 判断成立
break
done
[root@localhost opt]# vim arr03.sh
#!/bin/bash
#创建任意数字及长度的数组,根据客户需求
i=0 #数组下标
while true
do
read -p "是否存入元素(yes/no):" doing
if [ $doing == "no" ];then
break
fi
read -p "请输入第$[$i+1]个元素:" key
arr[$i]=$key
let i++
done
echo ${arr[*]}
echo ${#arr[@]} ##数组长度
[root@localhost opt]# sh arr03.sh
是否存入元素(yes/no):yes
请输入第1个元素:33
是否存入元素(yes/no):yes
请输入第2个元素:66
是否存入元素(yes/no):yes
请输入第3个元素:99
是否存入元素(yes/no):no
33 66 99
[root@localhost ~]# arr_number=(1 2 3 4 5)
[root@localhost ~]# arr_length=${#arr_number[*]}
[root@localhost ~]# echo $arr_length
5
[root@localhost ~]# arr_length_1=${#arr_number[@]}
[root@localhost ~]# echo $arr_length_1
5
[root@localhost ~]# arr_index2=${arr_number[2]} //第三个元素
[root@localhost ~]# echo $arr_index2
3
[root@localhost ~]# vim array_traverse.sh
#!/bin/bash
arr_number=(1 2 3 4 5)
for v in ${arr_number[@]}
do
echo $v
done
[root@localhost ~]# chmod +x array_traverse.sh
[root@localhost ~]# ./array_traverse.sh
1
2
3
4
5
[root@centos-7 ~]# arr=(1 2 3 4 5)
[root@centos-7 ~]# echo ${arr[@]} //输出整个数组
1 2 3 4 5
[root@centos-7 ~]# echo ${arr[@]:0:2} //${数组名[@或*]:起始位置:长度}
1 2
[root@centos-7 ~]# echo ${arr[@]:2:3}
3 4 5
将数组切片之后,返回的是字符串,以空格作为分隔符。
[root@centos-7 ~]# arr=(1 2 3 4 5)
[root@centos-7 ~]# echo ${arr[@]/4/66} //${数组名[@或*]/查找字符/替换字符}
1 2 3 66 5
[root@centos-7 ~]# echo ${arr[@]} //并不会替换数组原有内容
1 2 3 4 5
[root@centos-7 ~]# arr=(${arr[@]/4/66}) //要实现改变原有数组,可通过重新赋值实现
[root@centos-7 ~]# echo ${arr[@]}
1 2 3 66 5
只是临时的更改输出,把原来的一份复制到缓冲区中,原来的没变
永久修改就把原来内容的覆盖掉
num=(${num[*]/44/88})
[root@centos-7 ~]# arr=(1 2 3 4 5)
[root@centos-7 ~]# unset arr //删除数组
[root@centos-7 ~]# echo ${arr[*]}
[root@centos-7 ~]# arr=(1 2 3 4 5)
[root@centos-7 ~]# unset arr[2] //删除第三个元素
[root@centos-7 ~]# echo ${arr[*]}
1 2 4 5
示例
删除低于数组中低于60分的成绩:
[root@localhost opt]# vim chengji04.sh
#!/bin/bash
score=(77 88 55 33 99 44)
i=0
for v in ${score[@]};do
if [ ${score[$i]} -lt 60 ];then
unset score[$i]
fi
let i++
done
echo ${score[@]}
[root@localhost opt]# sh chengji04.sh
77 88 99
echo 命令是最有用的调试脚本工具之一,一般在可能出现问题的脚本中加入 echo 命令,采用的是分段排查的方式
命令的语法为
sh [-nvx] 脚本名
常用参数的具体含义为:
set -x //开启调试模式
set +x //关闭调试模式
#!/bin/bash
set -x //开启调试模式
read -p "请输入您的分数(0-100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ]
then
echo "$GRADE 分!优秀"
set +x //关闭调试模式
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ]
then
echo "$GRADE 分,合格"
else
echo "$GRADE 分?不合格"
fi