读取不同的变量值,用来逐个执行同一组命令。for循环可实现遍历,即把集合中的元素逐个取一遍,执行命令;也可实现指定次数循环。
[root@localhost ~]# vim pinghost01.sh
#!/bin/bash
#
List=$(cat /opt/hostname)
for host in $List
do
ping -c 3 -i 0.3 -W 3 $host &> /dev/null
if [ $? -eq 0 ]
then
echo "host $host up"
else
echo "host $host down"
fi
done
[root@localhost ~]# cat /opt/hostname ###需要创建文件,让脚本去取
20.0.0.1
20.0.0.2
20.0.0.111
[root@localhost ~]# bash pinghost01.sh
host 20.0.0.1 up
host 20.0.0.2 up
host 20.0.0.111 down
[root@localhost ~]#
[root@localhost ~]# vim /opt/username ##用户名存放在这里
lisa1
lisa2
[root@localhost ~]# vim usradd.sh
#!/bin/bash
#
List=$(cat /opt/username)
for username in $List
do
useradd $username
echo "123456" |passwd --stdin $username
done
[root@localhost ~]# bash usradd.sh
更改用户 lisa1 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 lisa2 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# tail -5 /etc/passwd
...
lisa1:x:1024:1024::/home/lisa1:/bin/bash
lisa2:x:1025:1025::/home/lisa2:/bin/bash
[root@localhost ~]# cat evil01.sh
#!/bin/bash
#
for ((i=1;i <= 5;i++))
do
echo $i
done
[root@localhost ~]# cat evil02.sh
#!/bin/bash
#
i=1
for ((;i <= 5;i++))
do
echo $i
done
[root@localhost ~]# cat evil03.sh
#!/bin/bash
#
for ((i=1;i <= 5;))
do
echo $i
let i++
done
[root@localhost ~]# cat evil04.sh
#!/bin/bash
#
for ((i=1;i <= 5;))
do
echo $i
i=$[$i + 1]
done
[root@localhost ~]# cat evil05.sh
#!/bin/bash
#
for ((i=1;i <= 5;))
do
echo $i
i=`expr $i + 1`
done
[root@localhost ~]# cat evil06.sh
#!/bin/bash
#
i=1
for ((;;))
do
if [ $i -le 5 ]
then
echo $i
let i++
else
exit 0
fi
done
[root@localhost ~]#
结果均为
[root@localhost ~]# bash evil06.sh
1
2
3
4
5
方法1:
[root@localhost ~]# vim echo01.sh
#!/bin/bash
#
sum=0
for ((i=1;i <= 5;i++))
do
if [ $[$i%2] -eq 0 ] ##[` expr $i %2` -eq 0]
then
sum=$[$i+$sum] ##sum=` expr $i + $sum`
fi
done
echo $sum
方法2:
[root@localhost ~]# cat echo01.sh
#!/bin/bash
#
sum=0
for ((i=1;i <= 5;i++))
do
if [ $[$i%2] -eq 0 ]
then
let sum=$sum+$i
fi
done
echo $sum
[root@localhost ~]# bash echo01.sh
6
重复测试某个条件,只要条件成立则反复执行。
[root@localhost ~]# vim echo02.sh
#!/bin/bash
#
i=1
t="ter"
while [ $i -le 5 ]
do
name=$t$i
useradd $name
echo "123456" |passwd --stdin $name
let i++
done
[root@localhost ~]#
[root@localhost ~]# bash echo02.sh
useradd:用户“ter1”已存在
更改用户 ter1 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 ter2 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 ter3 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 ter4 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 ter5 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# vim echo03.sh
#!/bin/bash
#
i=10
while [ $i -ge 0 ]
do
if [ `expr $i % 3` -eq 0 ]
then
let i--
continue
else
echo $i
let i--
fi
done
[root@localhost ~]# bash echo03.sh
10
8
7
5
4
2
1
[root@localhost ~]# vim while02.sh
#!/bin/bash
#
i=1
while [ $i -le 10 ]
do
if [ `expr $i % 3` -ne 0 ]
then
echo "$i"
let i++
else
let i++
fi
done
[root@localhost ~]# bash while02.sh
1
2
4
5
7
8
10
在双重循环中,外重循环控制行,内重循环控制列,当外重循环拿出一个元素来执行一次时,内重循环需要所有元素都执行一遍。
方法一:两个for循环实现了输出1x[1-9]…9[1-9]的功能,显然有很多输出的是我们不要的,-n可以不换行使结果横着打印,观察乘法口诀表第一行输出1x1第二行输出2x1、2x2,i大于J时我们输出,使用if条件语句将不要的过滤,不符合条件时的break打断当前循环不输出并使用echo “”实现换行,到一次循环就在下一行了
[root@localhost ~]# vim w.sh
#!/bin/bash
#
for ((i=1;i<=9;i++))
do
for ((j=1;j<=9;j++))
do
if [ $i -ge $j ];then
name="$j x $i" ##也可以使用"$i x $j"可能更助于理解,在后面为了美观才调的
echo -ne "${name}=`expr $i \* $j` " ##这行最后有空格,列之间的空格
else
echo ""
break
fi
done
done
[root@localhost ~]# bash w.sh
1 x 1=1
1 x 2=2 2 x 2=4
1 x 3=3 2 x 3=6 3 x 3=9
1 x 4=4 2 x 4=8 3 x 4=12 4 x 4=16
1 x 5=5 2 x 5=10 3 x 5=15 4 x 5=20 5 x 5=25
1 x 6=6 2 x 6=12 3 x 6=18 4 x 6=24 5 x 6=30 6 x 6=36
1 x 7=7 2 x 7=14 3 x 7=21 4 x 7=28 5 x 7=35 6 x 7=42 7 x 7=49
1 x 8=8 2 x 8=16 3 x 8=24 4 x 8=32 5 x 8=40 6 x 8=48 7 x 8=56 8 x 8=64
1 x 9=9 2 x 9=18 3 x 9=27 4 x 9=36 5 x 9=45 6 x 9=54 7 x 9=63 8 x 9=72 9 x 9=81
方法二:
核心在于j<=i,直接输出的想要的,echo -ne 中-n是表示不换行,-e是表示可识别转义符如\t
[root@localhost ~]# vim w1.sh
#!/bin/bash
#
for ((i=1;i<=9;i++))
do
for ((j=1;j<=i;j++))
do
name="$j x $i" ##对应1 x 2中1为j,2为i,观察规律,在j<=i时输出
echo -ne "$name=`expr $j \* $i` "
done
echo ""
done
[root@localhost ~]# bash w1.sh
1 x 1=1
1 x 2=2 2 x 2=4
1 x 3=3 2 x 3=6 3 x 3=9
1 x 4=4 2 x 4=8 3 x 4=12 4 x 4=16
1 x 5=5 2 x 5=10 3 x 5=15 4 x 5=20 5 x 5=25
1 x 6=6 2 x 6=12 3 x 6=18 4 x 6=24 5 x 6=30 6 x 6=36
1 x 7=7 2 x 7=14 3 x 7=21 4 x 7=28 5 x 7=35 6 x 7=42 7 x 7=49
1 x 8=8 2 x 8=16 3 x 8=24 4 x 8=32 5 x 8=40 6 x 8=48 7 x 8=56 8 x 8=64
1 x 9=9 2 x 9=18 3 x 9=27 4 x 9=36 5 x 9=45 6 x 9=54 7 x 9=63 8 x 9=72 9 x 9=81
[root@localhost ~]# vim techer03.sh
#!/bin/bash
for ((i=1;i<=5;i++))
do
for ((j=5;j>=i;j--))
do
echo -n " "
done
for ((k=1;k<=2*i-1;k++))
do
echo -n "*"
done
echo ""
done
[root@localhost ~]# bash techer03.sh
*
***
*****
*******
*********
其实内层的两个for语句相互较独立,但是第一个for循环为第二个for循环做了基础,使第二个for循环出现图形的起点向后移动,让我更清晰的看到shell脚本是由一系列按顺序执行命令的集合
重复测试某个条件,只要条件不成立则反复执行
[root@localhost ~]# vim until03.sh
#!/bin/bash
#
i=1
sum=0
until [ $i -eq 51 ]
do
let sum+=$i;let i++
done
echo $sum
[root@localhost ~]# bash until03.sh
1275
需求:
为指定用户发送在线消息
若指定用户不在线(未登陆系统),则每3s试一次,直至用户登录系统后再发送信息
用户名与消息通过位置参数传递给脚本
分析:
[root@localhost ~]# vim until04.sh
#!/bin/bash
#
username=$1
#执行脚本时格式不规范,显示提醒
if [ $# -lt 1 ];then
echo "请在${0}后输入,用户名和发送的消息"
exit 1
fi
#查看输入的用户是否为系统中的用户
if grep "^$username" /etc/passwd > /dev/null;then :
else
echo "The user not exist"
exit 2
fi
#查看用户是否在线,不在线则每隔3秒查询一次,在线则跳到下个语句
until who | grep "$username" > /dev/null;do
echo "The user not login"
sleep 3
done
#在线时,发送消息
echo "$2" | write "$username"
echo "${username}发送成功"
[root@localhost ~]# bash until04.sh ter5 h ##用户不在线,后登录
The user not login
The user not login
The user not login
ter5发送成功
[root@localhost ~]# bash until04.sh
请在until04.sh后输入,用户名和发送的消息
shell函数将命令序列按格式写在一起,可以方便重复使用命令序列
[root@localhost ~]# vim hansu01.sh
#!/bin/bash
#
function sum(){
read -p "请输入第一个整数:" num1
read -p "请输入第二个整数:" num2
SUM=$[$num1+$num2]
echo "和为:$SUM"
}
sum ##执行脚本的时候有这条函数名,系统才知道要执行哪个函数,就像一个命令一样
[root@localhost ~]# bash hansu01.sh
请输入第一个整数:1
请输入第二个整数:2
和为:3
[root@localhost ~]# vim hansu01.sh
#!/bin/bash
#
function sum(){
read -p "请输入第一个整数:" num1
read -p "请输入第二个整数:" num2
SUM=$[$num1+$num2]
echo "和为:$SUM"
return 100
}
number=`sum`
echo $? ###输出状态码
echo $number
[root@localhost ~]# bash hansu01.sh
请输入第一个整数:1
请输入第二个整数:2
100
和为:3
[root@localhost ~]# vim hansu01.sh
#!/bin/bash
#
function sum(){
#read -p "请输入第一个整数:" num1
#read -p "请输入第二个整数:" num2
SUM=$[$1+$2]
echo "和为:$SUM"
return 100
}
sum 1 2
[root@localhost ~]# bash hansu01.sh
和为:3
将函数脚本加到~/.bashrc下,在source ~./bashrc
例:
自己定义了一个函数sum
[root@localhost ~]# vim hansu01.sh
#!/bin/bash
#
function sum(){
read -p "请输入第一个整数:" num1
read -p "请输入第二个整数:" num2
SUM=$[$num1+num2]
echo "$SUM"
}
sum
加到家目录下的.bashrc文件里,即可在当前bash环境下直接调用
[root@localhost ~]# vim ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
#!/bin/bash ###这里为我们自己定义的函数
#
function sum(){
read -p "请输入第一个整数:" num1
read -p "请输入第二个整数:" num2
SUM=$[$num1+num2]
echo "$SUM"
}
##最后不用加调用函数的函数名了
[root@localhost ~]# source ~/.bashrc
[root@localhost ~]# sum
请输入第一个整数:1
请输入第二个整数:2
3
数组:相同类型数据的集合,如:arr=(11,22,33,44),数组是在内存中开辟了连续的空间,可配合循环使用。
[root@localhost ~]# num=(1 2 3) ##定义数组
[root@localhost ~]# echo ${num[*]} ##调用数组,*表示下标所有
1 2 3
[root@localhost ~]# echo ${num[0]} ##调用下标为0,也就是第一个元素
1
[root@localhost ~]#
[root@localhost ~]# num=([0]=1 [1]=2 [2]=3 ) ##定义数组
[root@localhost ~]# echo ${num[@]} ##调用数组,@与*差不多
1 2 3
[root@localhost ~]# echo ${num[1]}
2
[root@localhost ~]#
[root@localhost ~]# list="1 2 3" ##先定义列表
[root@localhost ~]# num=($list) ##再赋予给数组
[root@localhost ~]# echo ${num[*]}
1 2 3
[root@localhost ~]#
拓展
调某个元素会有问题,可盘,看是否可以输出某个元素
变量是否可以看成是只有一个元素的数组
[root@localhost ~]# vim g.sh
#!/bin/bash
#
num=`cat /opt/a.txt` ##a.txt的内容为1 2 3
i=1
echo ${num[*]}
echo ${num[0]}
echo ${num[1]}
echo ${i[0]}
echo $num
[root@localhost ~]# bash g.sh
1 2 3
1 2 3
1
1 2 3
[root@localhost ~]# bash g.sh
1 2 3
2
[root@localhost ~]# vim g.
[root@localhost ~]# vim g.sh
#!/bin/bash
#
list=`cat /opt/a.txt`
num=($list)
echo ${num[*]}
echo ${num[1]}
[root@localhost ~]# vim until05.sh
#!/bin/bash
#
i=1
until [ $i -eq 101 ]
do
echo $i >> /opt/100.txt
let i++
done
list=`cat /opt/100.txt`
num=($list)
echo ${num[*]}
[root@localhost ~]# bash until05.sh
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
常用在替换某一个元素
[root@localhost ~]# num[0]=1 ##定义
[root@localhost ~]# nmu[1]=2
[root@localhost ~]# num[2]=2
[root@localhost ~]# num[3]=3
[root@localhost ~]# echo ${num[*]}
1 2 2 3
[root@localhost ~]# num[2]=3 ##替换
[root@localhost ~]# num[3]=4
[root@localhost ~]# echo ${num[*]}
1 2 3 4
[root@localhost ~]#
用到第四种定义数组的方法
[root@localhost ~]# vim h.sh
#!/bin/bash
#
for ((i=0;i<=99;i++))
do
arr[$i]=$[$i+1]
done
echo ${arr[*]}
[root@localhost ~]# bash h.sh
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
这是我的第一想法,非常不符合逻辑,这样输出虽生成了奇数,但arr[0]、arr[2]…都不存在了,跳跃了
[root@localhost ~]# vim shuzu01.sh
#!/bin/bash
#
for ((i=1;i<=10;i++))
do
if [ `expr $i % 2` -ne 0 ]
then
arr[$i]=$[$i]
fi
done
echo ${arr[*]}
[root@localhost ~]# bash shuzu01.sh
1 3 5 7 9
正确做法
[root@localhost ~]# vim jishu01.sh
#!/bin/bash
#
#k=0
j=1
for ((i=0;i<=9;i++))
do
k=$[$i+$j]
let j++
if [ $k -le 10 ];then
arr[i]=$k
fi
done
echo ${arr[*]}
[root@localhost ~]# bash jishu01.sh
1 3 5 7 9
[root@localhost ~]# vim q.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[*]}
[root@localhost ~]# bash q.sh
是否存入元素(yes/no):yes
请存入第1个元素:1
是否存入元素(yes/no):yes
请存入第2个元素:3
是否存入元素(yes/no):yes
请存入第3个元素:5
是否存入元素(yes/no):yes
请存入第4个元素:6
是否存入元素(yes/no):no
1 3 5 6
[root@localhost ~]# arr=(1 2 3 4)
[root@localhost ~]# arr_length=${#arr[*]}
[root@localhost ~]# echo $arr_length
4
[root@localhost ~]#
[root@localhost ~]# vim r.sh
#!/bin/bash
#
num=(1 2 3 4)
for v in ${num[*]}
do
echo $v
done
[root@localhost ~]# bash r.sh
1
2
3
4
改进
[root@localhost ~]# bash z.sh
60 60 70 90
[root@localhost ~]# vim z.sh
#!/bin/bash
#
score=(55 60 70 90)
for ((i=0;i<${#score[*]};i++))
do
if [ ${score[$i]} -lt 60 ];then
new[$i]=60
else
new[$i]=${score[$i]}
fi
done
echo ${new[*]}
[root@localhost ~]# vim m.sh
#!/bin/bash
#
score=(55 60 45 90)
temp=0
for ((i=0;i<${#score[*]};i++))
do
if [ ${score[$i]} -gt $temp ]
then
temp=${score[$i]}
fi
done
echo $temp
[root@localhost ~]# bash m.sh
90
[root@localhost ~]# vim m.sh
#!/bin/bash
score=(72 63 88 91 45)
for ((i=1;i<${#score[*];i++}))
do
for ((j=1;j<${#score[*]}-i;j++))
do
if [ ${score[$j] -gt ${score[`expr $j + 1`]} ];then
tmp=${score[`expr $j + 1`]
score[`expr $j + 1`]=${score[$j]}
score[$j]=$tmp
fi
done
done
echo ${score[*]}