Shell 编程中的循环
- Shell 中控制循环的命令:
for
、while
、until
、break
、continue
1. for 循环语句;
# 语法结构:
# 将 list 中的一系列的项赋给 var 这个变量,在每一次循环中通过 var 这个变量来运行一系列的命令
# list 就是一个变量的集合。这个集合可以被分割成无数的子项。
# 而每一个子项会在循环的每一次赋给 var 变量并且在循环中的每一次执行
for var in list
do
commands
done
# 如何获取 list ?
# 1. 在 list 中使用直接列表
# 2. 从变量读取列表
# 3. 从命令读取列表
# 4. 从目录读取列表
# 演示 1:
vim ltest1
# 写入以下内容
#! /bin/bash
for val in Jan Febr Mar Apr May
do
echo "Month is $val"
done
# 保存后退出,给与执行权限
chmod u+x ltest1
# 执行脚本
./ltest1
# 输出
Month is Jan
Month is Febr
Month is Mar
Month is Apr
Month is May
# 演示 2:
vim ltest1
# 写入以下内容
#! /bin/bash
list="Jan Febr Mar Apr May"
for val in $list
do
echo "Month is $val in list"
done
# 保存后退出,执行脚本
./ltest1
# 输出
Month is Jan in list
Month is Febr in list
Month is Mar in list
Month is Apr in list
Month is May in list
# 演示 3:
vim ltestfile
# 写入以下内容
Jan Febr Mar Apr May
# 保存退出
vim ltest1
# 写入以下内容
#! /bin/bash
for val in `cat ltestfile`
do
echo "Month is $val in file"
done
# 保存后退出,执行脚本
./ltest1
# 输出
onth is Jan in file
Month is Febr in file
Month is Mar in file
Month is Apr in file
Month is May in file
# for 循环分隔符
# 默认分隔符:空格、制表符、换行符
# 以上三种作为一个数据行中数据分列表的分隔符
# 修改分隔符:
IFS=$";" # 意思是:分隔符只保留分号,其它符号都无效
# 分隔符只对“变量读取列表”和“命令读取列表”有效,对直接使用列表数据无效。
# 从目录读取列表
# for 命令支持直接读取系统中的目录并将目录作为一个列表在循环中使用
# 演示 4:
vim ltest2
# 写入以下内容
#! /bin/bash
# 使用目录
# for var in /data/shellscript/l*
# 使用命令
for var in ls /data/shellscript/l*
do
echo "$var"
done
# 保存后退出,给与执行权限
chmod u+x ltest2
# 执行脚本
./ltest2
# 返回
/data/shellscript/ltest1
/data/shellscript/ltest2
/data/shellscript/ltestfile
# 在 Bash 中,还提供了另外一种 for 的语法结构
# 和 C 语言类型的 for 循环语法差不多
for((i=1;i<=10;i++))
do
commands
done
# 演示
vim ltest3
# 写入以下内容
#! /bin/bash
for ((i=1,j=5; i<=5; i++,j--))
do
echo "The number is $i $j"
done
# 保存后退出,给与执行权限
chmod u+x ltest3
# 执行脚本
./ltest3
# 输出
The number is 1 5
The number is 2 4
The number is 3 3
The number is 4 2
The number is 5 1
2. while 和 until 语句;
# while 语法结构
# if 语句中也有 test 命令
# test 是一个用来做条件判断的命令,
# 当 command 执行成功时,test 会返回 0 的退出码,不成功会返回 1
# while 语法意思是:当条件成立时,来执行其中的命令
while test command
do
commands
done
# until 语法结构
# until 语法意思是:直到这个命令成功时,退出循环
# while 和 until 在逻辑上是相反的
until test command
do
commands
done
# 演示 1:
vim ltest4
# 写入以下内容
#! /bin/bash
var=1
# test 命令可以用方括号代替
# 在使用 test 命令时,数值型的比较符号是用转义字符来实现的
while [ $var -lt 5 ]
do
echo "$var"
# expr 命令可以用“$[]”代替,里面的符号不用转义
var=$[ $var+1 ]
done
# 保存后退出,给与执行权限
chmod u+x ltest4
# 执行脚本
./ltest4
# 输出
1
2
3
4
# 演示 2:
vim ltest4
# 写入以下内容
#! /bin/bash
var=1
# 到 5, 退出循环
until [ $var -eq 5 ]
do
echo "$var"
var=$[ $var+1 ]
done
# 保存后退出,执行脚本
./ltest4
# 输出
1
2
3
4
3. 循环的嵌套和控制。
# 循环是可以嵌套的(for、while、until 都支持嵌套)
# 演示 1,使用 for:
vim ltest5
# 写入以下内容
#! /bin/bash
for(( i=1; i<=3; i++))
do
echo "outside loop:$i"
for(( j=1; j<=3; j++))
do
echo "inside loop:$j"
done
done
# 保存后退出,给与执行权限
chmod u+x ltest5
# 执行脚本
./ltest5
# 输出
outside loop:1
inside loop:1
inside loop:2
inside loop:3
outside loop:2
inside loop:1
inside loop:2
inside loop:3
outside loop:3
inside loop:1
inside loop:2
inside loop:3
# 演示 2,使用 while:
vim ltest5
# 写入以下内容
#! /bin/bash
i=1
while [ $i -le 3 ]
do
echo "outside loop:$i"
for(( j=1; j<=3; j++))
do
echo "inside loop:$j"
done
i=$[ $i+1 ]
done
# 保存后退出,执行脚本
./ltest5
# 输出结果和上面一样
# 跳出循环:break
# 继续循环:continue
# 演示:
vim ltest6
# 写入以下内容
#! /bin/bash
for (( i=1; i<=10; i++))
do
if [ $i -eq 5 ]
then
break;
fi
echo "$i"
done
# 保存后退出,给与执行权限
chmod u+x ltest6
# 执行脚本
./ltest6 # 输出 1 2 3 4
# 如果上述脚本中把 continue 替换 break
# 则输出 1 2 3 4 6 7 8 9 10
# 更复杂的演示
# 通过循环和条件判断写一个脚本,输出指定用户名的相关配置
vim ltest7
# 写入以下内容
#! /bin/bash
echo "please input a user:"
read uname
# /etc/passwd 的数据都是以行的形式提供的,并且每一行通过“:”划分成不同的数据段
# 需要查找的用户名在数据段的第一段
# 所以需要做循环嵌套,也要使用不同的分隔符进行数据的分割
IFS=$'\n'
# 提取每一行的数据
for row in `cat /etc/passwd`
# 每一次循环中拿到 row 变量,在这个变量中存储了每一个用户的信息
do
# 对 row 进行进一步的分割
IFS=$':'
# 匹配冒号分割后的第一段(也就是用户名),所以需要计数
i=1
is_target=0
# 从 row 这个变量中提取冒号分割的每一段的数据
for value in $row
do
# i=1,也就是获取了每行冒号分割后的第一段数据,
# 就是用户名,是不是输入的用户名
if [ $i -eq 1 ] && [ $value = $uname ]
then
# 如果已经找到了需要的数据行,标记 is_target=1
is_target=1
fi
i=$[ $i+1 ]
if [ $is_target -eq 1 ]
then
# 输出找到了的数据行中冒号分割的每一段的数据
echo $value
fi
done
# 输出找到了的数据行的整行的信息
if [ $is_target -eq 1 ]
then
echo $row
# 输出后直接跳出
break
fi
done
# 保存后退出,给与执行权限
chmod u+x ltest7
# 执行脚本
./ltest7
# 输入
root
# 输出
root
x
0
0
root
/root
/bin/bash
root x 0 0 root /root /bin/bash