【Linux系列教程】Shell逻辑控制——循环

一、Shell循环的几个方式

  • for
  • while
  • until

二、for循环

1.格式

for 变量 in 取值列表; do
    执行的操作
    执行的操作
done
for 变量 in 取值列表
do
    执行的操作
    执行的操作
done

2.示例:在tmp目录创建20个随机数文件

#!/bin/bash
#

for i in $(seq 20); do	#seq后面跟着数字代表这个命令输出多少次数
    touch /tmp/$(openssl rand -hex 10)
done

3.示例:创建30个用户,并且判断用户是否存在,密码统一设置为redhat

#! /bin/bash
#
 
for i in $(seq 30); do
#判断用户是否存在
if id user$i &> /dev/null; then
     echo "用户user$i存在"
     else
#如果不存在,创建用户并且设置密码
     useradd user$i &> /dev/null
     echo "redhat" | passwd --stdin user$i &> /dev/null
     echo "用户user$i创建成功,初始密码为redhat"
fi
done

4.删除刚刚创建30个用户

#! /bin/bash
# 
for i in $(seq 30); do
if id user$i &> /dev/null; then
     userdel -r user$i &> /dev/null
     echo "用户user$i删除完成"
 else
     echo "用户user$i可能已经删除,或删除失败"
 fi
 done

5.创建文件里指定的用户

[root@master ~]# cat user_list 
wsjj
student
martin
wanggang

#! /bin/bash

for i in $(cat /root/user_list);do
useradd  $i &> /dev/null
if [ $? -eq 0 ]; then
    echo "成功创建用户$i"
else
    echo "用户$i创建失败"
fi

done

6.示例:统计系统/bin/bash用户和/sbin/nologin用户有多少个

[root@master ~]# grep -i "/bin/bash$" /etc/passwd | wc -l
5
[root@master ~]# grep -i "/sbin/nologin$" /etc/passwd | wc -l
16
#! /bin/bash

bin_bash=0
sbin_nologin=0

number=$(wc -l /etc/passwd | awk '{print $1}')	#passwd文件所有用户数量

for i in $(seq $number); do	#
    sh_name=$(head -n $i /etc/passwd | tail -n1 | awk -F: '{print $7}')
    if [ $sh_name == "/bin/bash" ]; then
        let bin_bash++
    elif [ $sh_name == "/sbin/nologin" ]; then
        let sbin_nologin++
    fi
done
echo "bash:$bin_bash nologin:$sbin_nologin"

[root@master ~]# ./passwd.sh 
bash:5 nologin:16

7.shell字符串处理

A.字符串替换

[root@localhost ~]# data=abc
[root@localhost ~]# echo ${data/b/K}
aKc

B.截取字符串

[root@localhost ~]# data="linux"
[root@localhost ~]# 
[root@localhost ~]# echo ${data:0:2}
li
[root@localhost ~]# echo ${data:2:2}
nu
[root@localhost ~]# echo ${data:1}
inux

C.获取字符串长度

root@localhost ~]# data="linux"

[root@localhost ~]# echo ${#data}
5

三、中断循环

  • break 中断整体循环
  • continue 中断本次循环,立即开始下一次循环
#!/bin/bash
#

for i in $(seq 5); do
    echo "第$i次循环开始"
    if [ $i -eq 3 ]; then
       break
    fi
    echo "--------------"
    echo "第$i次循环结尾"
done
#!/bin/bash
#

for i in $(seq 5); do
    echo "第$i次循环开始"
    if [ $i -eq 3 ]; then
       continue
    fi
    echo "--------------"
    echo "第$i次循环结尾"
done

1.示例:查看本机路由表所有的IP+MAC地址

#! /bin/bash

host_ip=$(ifconfig | head -n 3 | grep "inet" | awk '{print $2}')
host_mac=$(ifconfig | head -n 3 | grep "ether" | awk '{print $2}')
echo "本机的IP地址:$host_ip 本机的Mac地址:$host_mac"
echo '===================================================='


for i in $(seq 254);do
{	#开启多线程
if [ $i -eq 128 ]; then
    continue	#使用continue终止第128次循环,128是本机IP
fi
net=10.10.10.
mac=`arping -I ens33 -c 1 -w 1 $net$i | head -n 2 | tail -n 1 | awk '{print $5}'`
    if  ping -W 1 -c 1 $net$i &> /dev/null ; then
    echo "检测到IP:$net$i Mac:$mac"
    else
    echo "没有这个$net$i主机" &> /dev/null
    fi
    }&	#开启多线程

done
wait	#等待多线程跑完再结束

四、while循环

1.用法1 while 条件

while 条件; do
    执行的操作
    执行的操作
done
#!/bin/bash
#

i=1

while [ $i -le 10 ]; do
    touch /tmp/$(openssl rand -hex 10)
    let i++
done

2.用法2 while true

死循环

while true; do
    执行的操作
    执行的操作
done

每隔2秒查看一次CPU状态

#!/bin/bash
#

while true; do	#一直循环下去
    uptime	#查看CPU负载状态
    sleep 2	#中断2秒
done

A.配置菜单界面,除非选择退出,否则永远不退出

#! /bin/bash

cat << eof
=======虚拟机管理工具============
1.创建虚拟机
2.销毁虚拟机
3.网络配置
4.退出
================================
eof

while true; do
    echo 
    read -p "请选择操作项: " a
    if [ $a -eq 1 ]; then
        echo "创建虚拟机"
    elif [ $a -eq 2 ]; then
        echo "销毁虚拟机"
    elif [ $a -eq 3 ]; then
        echo "网络配置"
    elif [ $a -eq 4 ]; then
        exit 0
    else
        echo "输入有误,请重新选择"
    fi

done
[root@master ~]# ./caidan.sh 
=======虚拟机管理工具============
1.创建虚拟机
2.销毁虚拟机
3.网络配置
4.退出
================================

请选择操作项: 1
创建虚拟机

请选择操作项: 2
销毁虚拟机

请选择操作项: 3
网络配置

请选择操作项: 3
网络配置

请选择操作项: 6
输入有误,请重新选择

请选择操作项: 4
[root@master ~]# 

用法3 while read line

  • 用于遍历文件, 处理文件每一行
while read line; do
    执行的操作
    执行的操作
done < 文件名称

处理命令的每行结果

#!/bin/bash
#

df -hT | while read line; do
    echo "---> $line"
done

统计passwd文件中有多少系统用户

#! /bin/bash

system_user=0
while read line; do
number=$(echo $line | awk -F: '{print $3}')
    if [ $number -ge 1 -a $number -le 999 ]; then	#排除root用户uid为0
    let system_user++
    fi
done < /tmp/passwd
    echo "当前系统存在$system_user个系统用户"

passwd文件中的数据,批量插入到mysql数据库中

#! /bin/bash

while read line; do
    name=$(echo $line | awk -F: '{print $1}')
    passwd=$(echo $line | awk -F: '{print $2}')
    uid=$(echo $line | awk -F: '{print $3}')
    gid=$(echo $line | awk -F: '{print $4}')
    shuoming=$(echo $line | awk -F: '{print $5}')
    home=$(echo $line | awk -F: '{print $6}')
    shell=$(echo $line | awk -F: '{print $7}')
mysql -uroot -e "insert into passwd.passwd(name, passwd, uid, gid, shuoming, home, shell) values('$name', '$passwd', $uid, $gid, '$shuoming', '$home', '$shell');"

done < /tmp/passwd

查看刚刚使用脚本导入的数据

MariaDB [passwd]> select * from passwd;
+-----------------+--------+------+------+-----------------------------------------------------------------+--------------------+----------------+
| name            | passwd | uid  | gid  | shuoming                                                           | home               | shell          |
+-----------------+--------+------+------+-----------------------------------------------------------------+--------------------+----------------+
| root            | x      |    0 |    0 | root                                                            | /root              | /bin/bash      |
| bin             | x      |    1 |    1 | bin                                                             | /bin               | /sbin/nologin  |
| daemon          | x      |    2 |    2 | daemon                                                          | /sbin              | /sbin/nologin  |
| adm             | x      |    3 |    4 | adm                                                             | /var/adm           | /sbin/nologin  |
| lp              | x      |    4 |    7 | lp                                                              | /var/spool/lpd     | /sbin/nologin  |
| sync            | x      |    5 |    0 | sync                                                            | /sbin              | /bin/sync      |
| shutdown        | x      |    6 |    0 | shutdown                                                        | /sbin              | /sbin/shutdown |
| halt            | x      |    7 |    0 | halt                                                            | /sbin              | /sbin/halt     |
| mail            | x      |    8 |   12 | mail                                                            | /var/spool/mail    | /sbin/nologin  |
| operator        | x      |   11 |    0 | operator                                                        | /root              | /sbin/nologin  |
| games           | x      |   12 |  100 | games                                                           | /usr/games         | /sbin/nologin  |
| ftp             | x      |   14 |   50 | FTP User                                                        | /var/ftp           | /sbin/nologin  |
| mysql           | x      |   27 |   27 | MariaDB Server                                                  | /var/lib/mysql     | /sbin/nologin  |
| tss             | x      |   59 |   59 | Account used by the trousers package to sandbox the tcsd daemon | /dev/null          | /sbin/nologin  |
| sshd            | x      |   74 |   74 | Privilege-separated SSH                                         | /var/empty/sshd    | /sbin/nologin  |
| dbus            | x      |   81 |   81 | System message bus                                              | /                  | /sbin/nologin  |
| postfix         | x      |   89 |   89 |                                                                 | /var/spool/postfix | /sbin/nologin  |
| nobody          | x      |   99 |   99 | Nobody                                                          | /                  | /sbin/nologin  |
| systemd-network | x      |  192 |  192 | systemd Network Management                                      | /                  | /sbin/nologin  |
| polkitd         | x      |  999 |  998 | User for polkitd                                                | /                  | /sbin/nologin  |
| wsjj            | x      | 1000 | 1000 |                                                                 | /home/wsjj         | /bin/bash      |
| student         | x      | 1001 | 1001 |                                                                 | /home/student      | /bin/bash      |
| martin          | x      | 1002 | 1002 |                                                                 | /home/martin       | /bin/bash      |
| wanggang        | x      | 1003 | 1003 |                                                                 | /home/wanggang     | /bin/bash      |
+-----------------+--------+------+------+-----------------------------------------------------------------+--------------------+----------------+
24 rows in set (0.00 sec)