七、循环结构化命令

for命令

创建一个遍历,每次迭代读取列表中的一个值。

迭代完成后,变量会保存最后一次迭代的值。

语法格式

第一种写法

for var in list
do    
    命令
done

第二种写法

for var in list;do
    命令
done

 第三种写法,c语言风格

for (( i=1;i<=10;i++ ))
do
        echo  $i
done
#或者
for (( i=1;i<=10;i++ )) 
{
  echo $i 
}

 

取值列表有多种方式,如取in后面的值,默认以空格分隔

举例

[root@tzPC ~]# cat for1.sh
#!/bin/bash
for var in a b c d
do
        echo "the text is $var"
done

 列表有复杂值,可以使用引号或者转义字符 \

举例

#!/bin/bash
for var in a b "c1 d1" e "hello world"
do
    echo $var
done

 如果有单引号,还可以使用\转义

[root@tzPC ~]# cat for2.sh
#!/bin/bash
for var in a b\'1 "c d" e "hello world" I\'s o
do
        echo $var
done
[root@tzPC ~]# bash for2.sh
a
b'1
c d
e
hello world
I's
o

 \会将后面的单引号转义

从变量中取值

#!/bin/bash
list="a1 b1 c1 d1"
for i in $list
do
    echo is a $i
done

 从命令中取值

[root@tzPC ~]# cat for3.sh
#!/bin/bash
for i in `bash for2.sh`
do
        echo $i
done

 结果

[root@tzPC ~]# bash for3.sh
a
b'1
c
d
e
hello
world
I's
o

从文件中取值

[root@tzPC 13Unit]# cat test5.sh 
#!/bin/bash
file="file"
for var in $(cat $file);do
        echo $var
done

 

自定义shell分隔符

默认情况下,base shell会以如下做为分隔符。

  • 空格
  • 制表符
  • 换行符

可通环境变量IFS(内部字段分隔符)来自定义为分隔符。

指定单个字符做分隔符:

IFS=:   #以:冒号做分隔符
#可以指定多个
如 IFS='\n':;"     #这个赋值会将反斜杠、n、冒号、分号和双引号作为字段分隔符。

 

注:$'\n'与'\n'时的区别

IFS='\n'    #将字符\和字符n作为IFS的换行符。

IFS=$'\n'   #使用换行符做为字段分隔符。

举例

[root@tzPC ~]# cat for4.sh
#!/bin/bash
IFS=$'\n'
for i in `cat /etc/hosts`
do
        echo $i
done
[root@tzPC ~]# bash for4.sh
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

 在一个地方修改IFS值,在脚本其他地方沿用IFS默认值

可以先将环境变量IFS的值赋给变量IFS_OLD,注意书中写的是赋值给IFS.OLD变量,在实验环境中会报错。

[root@tzPC 13Unit]# cat test5.sh 
#!/bin/bash
file="file"
IFS_OLD=$IFS
IFS=$'\n'
for var in $(cat $file);do
        echo $var
done
IFS=$IFS_OLD
for var in 1 2 3 4 5 
do 
        echo $var
done

 使用通配符读取目录

因为目录名跟文件名可能包含空格,所以$file变量名最好使用双引号圈起来。

[root@tzPC temp_script]# cat test6.sh
#!/bin/bash
for file in /usr/bin/*
do
    if [ -d "$file" ];then
        echo "$file" is a directory
    elif [ -f "$file" ];then
        echo "$file is a file"
    fi
done

 

也可以列出多个目录通配符

[root@tzPC 13Unit]# cat test6.sh
#!/bin/bash
for file in /usr/bin/* /etc/*
do
        if [ -d "$file" ];then
                echo "$file is a directory"
        elif [ -f "$file" ];then
                echo "$file is a file"
        fi
done

 

C语言风格的for命令

[root@tzPC ~]# cat for5.sh
#!/bin/bash
for (( i=1;i<=10;i++ ))
do
        echo num is $i
done
[root@tzPC ~]# bash for5.sh
num is 1
num is 2
num is 3
num is 4
num is 5
num is 6
num is 7
num is 8
num is 9
num is 10

 使用多个变量

举例:同时输出1-9的升序和降序

注意,结束循环条件只要满足其中一条即可,是或关系

[root@tzPC ~]# cat for6.sh
#!/bin/bash
for (( a=1,b=9;a<10;a++,b-- ))
do
        echo num is $a -$b
done
[root@tzPC ~]# bash for6.sh
num is 1 -9
num is 2 -8
num is 3 -7
num is 4 -6
num is 5 -5
num is 6 -4
num is 7 -3
num is 8 -2
num is 9 -1

 如上述脚本改成如下

[root@tzPC temp_script]# cat for6.sh
#!/bin/bash
for ((a=1,b=9;a<10,b>5;a++,b--))
do
    echo $a -$b
done
[root@tzPC temp_script]# bash for6.sh
1 -9
2 -8
3 -7
4 -6

 

while命令

只要测试条件成立,就重复执行命令

语法格式

while test command
do
   other commands
done

 最常见的方式是使用方括号来检查循环命令

举例:降序输出10到1的数字

[root@tzPC ~]# cat while1.sh
#!/bin/bash
var=10
while [ $var -gt 0  ]
do
        echo $var
        var=$[ $var-1 ] 
   #或var=$(($var-1))或((var--))的写法都可以
done

 

举例2:输出如下图两数相乘的结果

自增操作 let var++

自减操作 let var--

[root@tzPC ~]# cat while2.sh
#!/bin/bash
num=1
while [ $num -lt 10 ]
do
        sum=$(( $num * $num ))
        echo "$num * $num = $sum"
        ((num++ ))
# let num++
done

 使用多个测试命令

while命令可以定义多个测试命令,但只有最后一个测试命令的退出码会被用来决定结束循环。

每条测试命令需独占一行。

[root@tzPC 13Unit]# cat test7.sh
#!/bin/bash
var1=10
while echo $var1
        [ $var1 -ge 0 ]
do
        echo "This is inside the loop"
        var1=$[ $var1 - 1 ]
done

 

until命令

与while命令工作方式相反,只有测试命令的退出状态码不为0(也就是条件不成立时),才会执行循环体,一旦测试命令返回退出状态码0,循环结束。

同样支持多个测试命令,最后一个测试命令退出码决定是否执行循环体。

语法格式

until test commands
do
    other commands
done

 

举例

[root@tzPC 13Unit]# bash test8.sh
100
75
50
25
[root@tzPC 13Unit]# cat test8.sh
#!/bin/bash
#using the until command
var1=100
until [ $var1 -eq 0 ] #当$var1不等于0时才执行循环
do
        echo $var1
        var1=$[ $var1 -25 ]
done

 

嵌套循环

循环语句可以在循环内使用循环命令,在迭代中使用迭代,与命令运行的次数是乘积关系。

举例for循环嵌套for循环

[root@tzPC 13Unit]# bash test14.sh
Starting loop 1:
        Inside loop:1
        Inside loop:2
        Inside loop:3
Starting loop 2:
        Inside loop:1
        Inside loop:2
        Inside loop:3
Starting loop 3:
        Inside loop:1
        Inside loop:2
        Inside loop:3
[root@tzPC 13Unit]# cat test14.sh
#!/bin/bash
#nesting for loops
for (( a = 1; a <= 3; a++ ))
do
        echo "Starting loop $a:"
        for (( b = 1; b <= 3; b++ ))
        do
                echo "  Inside loop:$b"
        done
done

 while嵌套for循环

[root@tzPC 13Unit]# bash test15.sh
Outer loop:5
        Inner loop: 5 * 1 =5
        Inner loop: 5 * 2 =10
Outer loop:4
        Inner loop: 4 * 1 =4
        Inner loop: 4 * 2 =8
Outer loop:3
        Inner loop: 3 * 1 =3
        Inner loop: 3 * 2 =6
Outer loop:2
        Inner loop: 2 * 1 =2
        Inner loop: 2 * 2 =4
Outer loop:1
        Inner loop: 1 * 1 =1
        Inner loop: 1 * 2 =2
Outer loop:0
        Inner loop: 0 * 1 =0
        Inner loop: 0 * 2 =0
[root@tzPC 13Unit]# cat test15.sh
#!/bin/bash
#placing a for loop inside a while loop
var1=5
while [ $var1 -ge 0 ]
do
        echo "Outer loop:$var1"
        for (( var2 = 1; $var2 <3; var2++ ))
        do
                var3=$[ $var1 * $var2 ]
                echo "  Inner loop: $var1 * $var2 =$var3"
        done
        var1=$[ $var1 - 1 ]#使用((var1--))方便
done

 

 until嵌套while循环

[root@tzPC 13Unit]# bash test16.sh
Outer loop:3
        Inner loop:3 / 1 = 3.0000
        Inner loop:3 / 2 = 1.5000
        Inner loop:3 / 3 = 1.0000
        Inner loop:3 / 4 = .7500
Outer loop:2
        Inner loop:2 / 1 = 2.0000
        Inner loop:2 / 2 = 1.0000
        Inner loop:2 / 3 = .6666
        Inner loop:2 / 4 = .5000
Outer loop:1
        Inner loop:1 / 1 = 1.0000
        Inner loop:1 / 2 = .5000
        Inner loop:1 / 3 = .3333
        Inner loop:1 / 4 = .2500
[root@tzPC 13Unit]# cat test16.sh
#!/bin/bash
#using until and while loops
var1=3
until [ $var1 -eq 0 ]
do 
        echo "Outer loop:$var1"
        var2=1
        while [ $var2 -lt 5 ]
        do      
                var3=$(echo "scale=4;$var1 / $var2" | bc)
                echo "  Inner loop:$var1 / $var2 = $var3"
                var2=$[ $var2 + 1 ]     
        done
        var1=$[ $var1 - 1 ]
done

 

循环处理文件数据

注意两点

  • 使用嵌套循环
  • 修改IFS环境变量
打印/etc/passwd各个字段
[root@tzPC 13Unit]# bash test17.sh
Values in root:x:0:0:root:/root:/bin/bash 
        root
        x
        0
        0
        root
        /root
        /bin/bash

 脚本如下

[root@tzPC 13Unit]# cat test17.sh
#!/bin/bash
#changing the IFS value
IFS_OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
        echo "Values in $entry "
        IFS=:
        for value in $entry
        do
                echo "  $value"
        done
done

 

添加user.txt文件中的5个用户。

[root@tzPC ~]# cat useradd.sh
#!/bin/bash
for name in `cat /root/useradd.txt`
do
        id $name &> /dev/null
        if [ $? -eq 0 ] ;then
                echo "user $name created"
        else
                useradd $name
                echo "123456" | passwd --stdin $name &> /dev/null
        fi
done

 可以根据添加用户写一个删除用户,自己动手,我已经写出来了哈哈

2020年8月26日复习于此,加油我看好我自己。

打印九九乘法表

注意:外层循环行,内层循环列

规律:第二个变量小于等于第一个变量

seq 9表示从1连续输出到9

[root@tzPC ~]# seq 9
1
2
3
4
5
6
7
8
9

 

脚本

[root@tzPC ~]# bash for_99.sh
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
[root@tzPC ~]# cat for_99.sh
#!/bin/bash
for i in `seq 9`
do
        for j in `seq 9`
        do
        [ $j -le $i ] && echo -n "$i*$j=`echo $(($i*$j))` "
        done
        echo "  "
done

  学习来自:《Linux命令行与Shell脚本大全 第3版》第13章

posted @ 2020-07-17 10:49  努力吧阿团  阅读(221)  评论(0编辑  收藏  举报