一:for循环语句
1:for循环语句的结构
for 变量名 in 取值列表
do
命令序列
done
注意:for循环语句需要有一个取值列表
备注:
for 语句的执行流程:首先将列表中的第一个取值赋给变量,并执行 do…done 循环体
中的命令序列;然后将列表中的第二个取值赋给变量,并执行循环体中的命令序列……依此
类推,直到列表中的所有取值用完,最后将跳至 done 语句,表示结束循环
2:案例 根据姓名列表批量添加用户
(1)创建用户的列表文件
[root@localhost ~]# vim /root/users.txt
zhangsan
lisi
wangwu
(2)编辑批量添加用户的脚本
[root@localhost ~]# vim uaddfor.sh
#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
useradd $UNAME
echo "123456" | passwd --stdin $UNAME &>/dev/null
done
给脚本赋予执行权限
[root@localhost ~]# chmod 755 uaddfor.sh
测试并确认执行结果
[root@localhost ~]#./uaddfor.sh
[root@localhost ~]# tail -3 /etc/passwd
(3)编辑批量删除用户的脚本
[root@localhost ~]# vim udelfor.sh
#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
userdel -r $UNAME &>/dev/null
done
给脚本赋予执行权限
[root@localhost ~]# chmod a+x udelfor.sh
测试并确认执行结果
[root@localhost ~]#./udelfor.sh
[root@localhost ~]# id zhangsan
3:案例 根据 IP 地址列表检查主机状态
1)创建IP地址列表文件
[root@localhost ~]# vim /root/ipadds.txt
172.16.1.1
172.16.1.111
172.16.1.222
192.168.10.10
2)编辑循环检查各主机的脚本
[root@localhost ~]# vim chkhosts.sh
#!/bin/bash
HLIST=$(cat /root/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ]
then
echo "Host $IP is up."
else
echo "Host $IP is down."
fi
done
[root@localhost ~]# chmod a+x chkhost.sh
测试并确认执行结果
[root@localhost ~]#./chkhosts.sh
二:使用 while 循环语句
1:while语句的语法结构
while 条件测试操作
do
命令序列
done
备注:
while 语句的执行流程:首先判断 while 后的条件测试操作结果,如果条件成立,则执
行 do…done 循环体中的命令序列;返回 while 后再次判断条件测试结果,如果条件仍然成
立,则继续执行循环体;再次返回到 while 后,判断条件测试结果……如此循环,直到 while
后的条件测试结果不再成立为止,最后跳转到 done 语句,表示结束循环
2:案例 批量添加规律编号的用户
1)批量添加用户脚本
[root@localhost ~]# vim uaddwhile.sh
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
useradd ${PREFIX}$i
echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
let i++
done
[root@localhost ~]# chmod a+x uaddwhile.sh
测试并确认执行结果
[root@localhost ~]#./uaddwhile.sh
[root@localhost ~]# grep "stu" /etc/passwd | tail -3
或者
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
useradd ${PREFIX}$i
echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
i=`expr $i + 1`
done
[root@localhost ~]# chmod a+x uaddwhile.sh
测试并确认执行结果
[root@localhost ~]#./uaddwhile.sh
[root@localhost ~]# grep "stu" /etc/passwd | tail -3
2)批量删除用户脚本
[root@localhost ~]# vim udelwhile.sh
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
userdel -r ${PREFIX}$i
let i++
done
[root@localhost ~]# chmod a+x udelwhile.sh
测试并确认执行结果
[root@localhost ~]#./udelwhile.sh
id stu20
3:案例 猜价格游戏
[root@localhost ~]# vim pricegame.sh
#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
TIMES=0
echo "商品实际价格范围为0-999,猜猜看是多少?"
while true
do
read -p "请输入你猜测的价格数目:" INT
let TIMES++
if [ $INT -eq $PRICE ] ; then
echo "恭喜你答对了,实际价格是 $PRICE"
echo "你总共猜测了$TIMES 次"
exit 0
elif [ $INT -gt $PRICE ] ; then
echo "太高了!"
else
echo "太低了!"
fi
done
[root@localhost ~]# chmod a+x pricegame.sh
注意:linux中随机数的取值范围是0--32767,和什么数取余,取余后的最大数就是谁,不包含该数字
测试并确认执行结果
[root@localhost ~]#./pricegame.sh
商品实际价格范围为0-999,猜猜看是多少?
请输入你猜测的价格数目:500
太高了!
......
三:until 循环语句
1:until 语句的结构
until 条件测试操作
do
done
备注:
until 语句的执行流程:首先判断 until 后的条件测试操作结果,如果条件不成立,则执
行 do…done 循环体中的命令序列;返回 until 后再次判断条件测试结果,如果条件仍然不
成立,则继续执行循环体;再次返回到 until 后,判断条件测试结果……如此循环,直到 until
后的条件测试结果成立为止,最后跳转到 done 语句
直到条件满足后才会停止循环
2:until语法案例
(1)案例一
[root@localhost ~]# vim until_v1.sh
#!/bin/bash
i=0;s=0
until [ $i -eq 50 ]
do
let "i=$i+1";let "s=$s+$i"
done
echo 'sum(1..50)='$s
[root@localhost ~]# chmod +x sum1to50_until_v1.sh
[root@localhost ~]# ./sum1to50_until_v1.sh
sum(1..50)=1275
(1)案例二
[root@localhost ~]# vim until_v2.sh
var1=100
until [ $var1 -eq 0 ]
do
echo $var1
var1=$[ $var1 - 25 ]
done
[root@localhost ~]# chmod +x until_v2.sh
[root@localhost ~]# ./until_v2.sh
四:Shell 函数
Shell 函数可用于存放一系列的指令。在 Shell 脚本执行的过程中,函数被置于内存中,
每次调用函数时不需要从硬盘读取,因此运行的速度比较快。在 Shell 编程中函数并非是必
须的元素,但使用函数可以对程序进行更好的组织。将一些相对独立的代码变成函数,可以
提高程序可读性与重用性,避免编写大量重复代码。
1:函数的用法
[function] 函数名() {
[return x]
}
- “function”关键字表示定义一个函数,可以省略;
- “{”符号表示函数执行命令的入口,该符号可以与函数名同行也可以在函数名下一行的句首;
- “}”符号表示函数体结束,两个大括号之间{ }是函数体;
- “命令序列”部分可以是任意的 Shell 命令,也可以调用其他函数;
- “return”表示退出函数返回一个退出值,通过返回值判断执行是否成功,也可以使用 exit 终止整个 Shell 脚本。
2:案例 一个简单的函数脚本
[root@localhost ~]# vim exa1.sh
#!/bin/bash
zhangsan() {
echo "my name is zhangsan"
}
lisi() {
echo "my name is lisi"
}
zhangsan
lisi
[root@localhost ~]# sh exa1.sh
3:案例 带有参数的shell函数示例
[root@localhost ~]#vim exa2.sh
#!/bin/bash
name() {
echo "my name is $1"
}
name $1
[root@localhost ~]# sh exa2.sh zhangsan
my name is zhangsan
[root@localhost ~]# sh exa2.sh lisi
my name is lisi
4:案例 函数变量的作用范围
[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
备注:
通过内置命令 local 将变量的值限定在函数内部。
五:Shell 数组
在 Shell 脚本中,数组是一种常见的数据结构,主要的应用场景包括:获取数组长度、
获取元素长度、遍历元素、元素切片、元素替换、元素删除等等。Shell 中的数组与 Java、
C、Python 不同,只有一维数组,没有二维数组。
1:定义数组的方法
数组常用定义方法包括以下几种。
方法一:
数组名=(
value0 value1 value2 ...)
方法二:
数组名=(
[0]=value [1]=value [2]=value ...)
方法三:
列表名=”value0 value1 value2 ...”
数组名=(
$列表名)
方法四:
数组名[0]=”value”
数组名[1]=”value”
数组名[2]=”value”
2:获取数组长度
[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
备注:
$* 和 $@ 都表示传递给函数或脚本的所有参数,我们已在《Shell特殊变量》一节中进行了演示,本节重点说一下它们之间的区别。
当 $* 和 $@ 不被双引号" "包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。
但是当它们被双引号" "包含时,就会有区别了:
"∗ " 会 将 所 有 的 参 数 从 整 体 上 看 做 一 份 数 据 , 而 不 是 把 每 个 参 数 都 看 做 一 份 数 据 。 " *"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。 "∗"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。
"@"仍然将每个参数都看作一份数据,彼此之间是独立的。
比如传递了 5 个参数,那么对于"∗ " 来 说 , 这 5 个 参 数 会 合 并 到 一 起 形 成 一 份 数 据 , 它 们 之 间 是 无 法 分 割 的 ; 而对于"@"来说,这 5 个参数是相互独立的,它们是 5 份数据。
[root@localhost ~]# vim aa
#!/bin/bash
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
[root@localhost ~]# bash aa 1 2 3
3:读取某下标赋值
[root@localhost ~]# arr_index2=${arr_number[2]}
或
[root@localhost ~]# echo ${arr_number[2]}
//第三个元素
[root@localhost ~]# echo $arr_index2
3
或
echo ${aaa[3]}
4:数组遍历
[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
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
备注:
切片就是输出数组中指定连续的若干位,从第几位开始的往后几个数
6:数组替换
[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
7:数组删除
[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]
//删除第三个元素
标签:语句,arr,shell,编程,echo,sh,done,root,localhost From: https://blog.csdn.net/weixin_71499831/article/details/139263222[root@centos-7 ~]# echo ${arr[*]}
1 2 4 5