shell script - loop

Posted by neylitalo on Wed, 12 Jan 2022 09:49:50 +0100

Run a code segment repeatedly several times, usually with conditions for entering the loop and exiting the loop

Number of repeated runs

  • The number of cycles is known in advance
  • The number of cycles is unknown in advance

Common circular commands: for, while, until

1, for loop

Format 1:

for NAME [in WORDS ... ] ; do COMMANDS; done

for Variable name [ in list ]; do
    Circulatory body
done

for Variable name [ in list ]
do
    Circulatory body
done

Implementation mechanism:

  • Assign the elements in the list to "variable name" in turn; Execute the loop body once immediately after each assignment; Knowing that the elements in the list are exhausted, the loop ends
  • If [in WORDS...] is omitted, In this case, the position parameter variable in "$@" is used

for loop list generation method:

  • Give a list directly
  • Integer list
    {start..end}
    $(seq [start [step]] end)
  • Command to return to list
    $(COMMAND)
  • Use glob, such as * sh
  • Variable references, such as $@, $*$#

Example 1, calculate 1 + 2 + 3 ++ 100 results:

[root@CentOS7 ~]# sum=0;for i in {1..100};do let sum+=$i;done ;echo sum=$sum
sum=5050
[root@CentOS7 ~]# seq -s+ 100|bc
5050

Example 2:

[root@CentOS7 ~]# cat for_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     for_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
sum=0
for i in $* ; do
    let sum+=$i
done
echo sum=$sum
[root@CentOS7 ~]# bash for_sum.sh 1 2 3 4 5 6
sum=21

Example 3, 99 multiplication table:

[root@CentOS7 ~]# cat haskell.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     haskell.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for i in {1..9};do
    for j in `seq $i`;do
        echo -e "${j}x${i}=$[i*j]\t\c"
    done
    echo
done
[root@CentOS7 ~]# bash haskell.sh 
1x1=1    
1x2=2    2x2=4    
1x3=3    2x3=6    3x3=9    
1x4=4    2x4=8    3x4=12    4x4=16    
1x5=5    2x5=10    3x5=15    4x5=20    5x5=25    
1x6=6    2x6=12    3x6=18    4x6=24    5x6=30    6x6=36    
1x7=7    2x7=14    3x7=21    4x7=28    5x7=35    6x7=42    7x7=49    
1x8=8    2x8=16    3x8=24    4x8=32    5x8=40    6x8=48    7x8=56    8x8=64    
1x9=9    2x9=18    3x9=27    4x9=36    5x9=45    6x9=54    7x9=63    8x9=72    9x9=81
[root@CentOS7 ~]# cat haskell1.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     haskell1.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for i in {1..9};do
    for j in `seq $i`;do
        let result=$[i*j]
        echo -e "${j}x${i}=$result\t\c"
    done
    echo
done
[root@CentOS7 ~]# bash haskell1.sh 
1x1=1    
1x2=2    2x2=4    
1x3=3    2x3=6    3x3=9    
1x4=4    2x4=8    3x4=12    4x4=16    
1x5=5    2x5=10    3x5=15    4x5=20    5x5=25    
1x6=6    2x6=12    3x6=18    4x6=24    5x6=30    6x6=36    
1x7=7    2x7=14    3x7=21    4x7=28    5x7=35    6x7=42    7x7=49    
1x8=8    2x8=16    3x8=24    4x8=32    5x8=40    6x8=48    7x8=56    8x8=64    
1x9=9    2x9=18    3x9=27    4x9=36    5x9=45    6x9=54    7x9=63    8x9=72    9x9=81

Format 2:

for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done

for ((Control variable initialization;Conditional judgment expression;Modified expression of control variable));do
  Circulatory body
done

Note:

  • Control variable initialization: executed only once when running to the loop code segment
  • Correction expression of control variable: at the end of each cycle, the correction operation of control variable will be carried out first, and then the condition judgment will be made

Example:

[root@CentOS7 ~]# cat for_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     for_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((sum=0,i=1;i<=100;i++)); do
        let sum+=i
done
echo sum=$sum
[root@CentOS7 ~]# bash for_sum.sh 
sum=5050
[root@CentOS7 ~]# cat for_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     for_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((sum=0,i=1;i<=100;sum+=i,i++)); do
        true
done
echo $sum
[root@CentOS7 ~]# bash for_sum.sh 
5050

Example 2, 99 multiplication table:

[root@CentOS7 ~]# cat haskell2.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     haskell2.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((i=1;i<10;i++));do
    for ((j=1;j<=i;j++));do
        echo -e "${j}x${i}=$((j*i))\t\c"
    done
    echo
done
[root@CentOS7 ~]# bash haskell2.sh 
1x1=1    
1x2=2    2x2=4    
1x3=3    2x3=6    3x3=9    
1x4=4    2x4=8    3x4=12    4x4=16    
1x5=5    2x5=10    3x5=15    4x5=20    5x5=25    
1x6=6    2x6=12    3x6=18    4x6=24    5x6=30    6x6=36    
1x7=7    2x7=14    3x7=21    4x7=28    5x7=35    6x7=42    7x7=49    
1x8=8    2x8=16    3x8=24    4x8=32    5x8=40    6x8=48    7x8=56    8x8=64    
1x9=9    2x9=18    3x9=27    4x9=36    5x9=45    6x9=54    7x9=63    8x9=72    9x9=81

2, while loop

Format:

while COMMANDS; do COMMANDS; done

while CONDITION; do
    Circulatory body
done

Note:

CONDITION: cycle control CONDITION; Make a judgment before entering the cycle; Judgment will be made again after each cycle; If the CONDITION is "TRUE", execute a cycle; The loop is terminated until the CONDITION test status is "FALSE". Therefore, the CONDITION should generally have a loop control variable; The value of this variable is constantly modified in the loop body

Entry CONDITION: CONDITION is TRUE

Exit CONDITION: CONDITION is FALSE

Infinite loop

while true; do
    Circulatory body
done

Example:

[root@CentOS7 ~]# cat while_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     while_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
i=1
sum=0
while [ $i -le 100 ];do
    let sum+=i
    let i++
done
echo sum=$sum
[root@CentOS7 ~]# bash while_sum.sh 
sum=5050

3, until loop

The working logic is similar to that of while. If the CONDITION is false, perform a cycle, if the CONDITION is true, exit the cycle

Format:

until COMMANDS; do COMMANDS; done

until CONDITION; do
    Circulatory body
done

explain:

Entry CONDITION: CONDITION is FALSE

Exit CONDITION: CONDITION is TRUE

Infinite loop

until false; do
    Circulatory body
done

Example 1:

[root@CentOS7 ~]# cat until_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     until_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
i=1
sum=0
until [ ! $i -le 100 ]; do
    let sum+=i
    let i++
done
echo sum=$sum
[root@CentOS7 ~]# bash until_sum.sh 
sum=5050

4, Loop control statement continue

continue [N], end the current cycle of layer N in advance and directly enter the next round of judgment; The innermost layer is the first layer

Format:

while CONDITION1; do
    CMD1
    ...
    if CONDITION2; then
        continue [N]
    fi
    CMDn
    ...
done

Example:

[root@CentOS7 ~]# cat continue.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            continue
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash continue.sh 
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=0
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=1
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=2
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=3
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=4
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=5
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=6
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=7
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=8
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=9
[root@CentOS7 ~]# cat continue.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            continue 2
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash continue.sh 
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4

5, Loop control statement break

break [N]: end the whole cycle of layer N in advance, and the innermost layer is layer 1

Format:

while CONDITION1;do
    CMD1
    ...
    if CONDITION2; then
        break [N]
    fi
    CMDn
done

Example:

[root@CentOS7 ~]# cat break.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            break
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash break.sh 
i=0
i=1
i=2
i=3
i=4
j=0
i=0
i=1
i=2
i=3
i=4
j=1
i=0
i=1
i=2
i=3
i=4
j=2
i=0
i=1
i=2
i=3
i=4
j=3
i=0
i=1
i=2
i=3
i=4
j=4
i=0
i=1
i=2
i=3
i=4
j=5
i=0
i=1
i=2
i=3
i=4
j=6
i=0
i=1
i=2
i=3
i=4
j=7
i=0
i=1
i=2
i=3
i=4
j=8
i=0
i=1
i=2
i=3
i=4
j=9
[root@CentOS7 ~]# cat break.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            break 2
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash break.sh 
i=0
i=1
i=2
i=3
i=4

Example:

[root@CentOS7 ~]# cat disk_check.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     disk_check.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
WARNING=80
while :;do
    USE=`df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2#p' | sort -nr | head -1`
        if [ $USE -gt $WARNING ] ; then
            echo DISK will be full from `hostname -I` | mail -s "Disk Warning" 1074035975@qq.com
            break
        fi
    sleep 10
done
[root@CentOS7 ~]# bash disk_check.sh
[root@CentOS7 ~]#

 

 

 

6, Loop control shift command

shift [n] is used to move the parameter list left a specified number of times. The default is to move left once.

Once the parameter list is moved, the leftmost parameter is deleted from the list. When the while loop traverses the position parameter list, shift is often used

Example:

[root@CentOS7 ~]# cat create_user.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     create_user.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
while [ "$1" ];do
    id $1 &> /dev/null || { useradd $1 ; echo $1 is created; }
    shift
done
[root@CentOS7 ~]# bash create_user.sh u1 u2 u3
u1 is created
u2 is created
u3 is created

7, while read special usage

Special usage of while loop, traversing every line of file or text; Use while read when processing line by line

Format:

while read line; do
    Circulatory body
done < /PATH/FROM/SOMEFILE

Note: read each line in the / PATH/FROM/SOMEFILE file in turn, and assign the line to the variable line

Example:

[root@CentOS7 ~]# seq 10
1
2
3
4
5
6
7
8
9
10
[root@CentOS7 ~]# seq 10 > a.txt
[root@CentOS7 ~]# echo user{1..10} | xargs -n1
user1
user2
user3
user4
user5
user6
user7
user8
user9
user10
[root@CentOS7 ~]# echo user{1..10} | xargs -n1 > user.txt
[root@CentOS7 ~]# paste -d' ' a.txt user.txt > users.txt
[root@CentOS7 ~]# cat users.txt 
1 user1
2 user2
3 user3
4 user4
5 user5
6 user6
7 user7
8 user8
9 user9
10 user10
[root@CentOS7 ~]# cat while_read.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     while_read.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
while read id name;do
    echo -e "id=$id\tname=$name"
done < users.txt
[root@CentOS7 ~]# bash while_read.sh 
id=1    name=user1
id=2    name=user2
id=3    name=user3
id=4    name=user4
id=5    name=user5
id=6    name=user6
id=7    name=user7
id=8    name=user8
id=9    name=user9
id=10    name=user10

Example 1 - send alarm mail when the hard disk is greater than 80% (infinite cycle):

[root@CentOS7 ~]# cat disk_check.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     disk_check.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
while :;do
    df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2 \1#p' | while read use dev; do
        [ $use -gt 80 ] && echo "$dev will be full,use: $use" | mail -s "Disk Warning" 1074035975@qq.com
    done
    sleep 10
done
[root@CentOS7 ~]# bash disk_check.sh 
^C
[root@CentOS7 ~]#
[root@CentOS7 ~]# cp /dev/zero /boot/disk.img
cp: error writing '/boot/disk.img': No space left on device
cp: failed to extend '/boot/disk.img': No space left on device
[root@CentOS7 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                   919504       0    919504   0% /dev
tmpfs                      931512       0    931512   0% /dev/shm
tmpfs                      931512   17984    913528   2% /run
tmpfs                      931512       0    931512   0% /sys/fs/cgroup
/dev/mapper/centos-root 104806400 4807772  99998628   5% /
/dev/sda1                 1038336 1038276        60 100% /boot
/dev/mapper/centos-data  52403200  227600  52175600   1% /data
tmpfs                      186304       0    186304   0% /run/user/0

 

 

Example 2 - send alarm mail when the hard disk is greater than 80% (cycle once):

[root@CentOS7 ~]# cat disk_check.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     disk_check.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
WRNING=80
USE1=`df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2#p' | sort -nr | head -1`
while :; do
    USE=`df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2#p' | sort -nr | head -1`
    if [ $USE -gt $WRNING ];then
        df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2 \1#p' | while read use dev;do
            [ $use -gt 80 ] && echo "$dev will be full,use:$use" | mail -s "Disk Warning" 1074035975@qq.com
        done
    echo "USE1=$USE1,use=$use,dev=$dev,WRNING=$WRNING,USE=$USE"
    break
    fi
    sleep 10
done
[root@CentOS7 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                   919504       0    919504   0% /dev
tmpfs                      931512       0    931512   0% /dev/shm
tmpfs                      931512   17984    913528   2% /run
tmpfs                      931512       0    931512   0% /sys/fs/cgroup
/dev/mapper/centos-root 104806400 4807440  99998960   5% /
/dev/sda1                 1038336  153668    884668  15% /boot
/dev/mapper/centos-data  52403200  227600  52175600   1% /data
tmpfs                      186304       0    186304   0% /run/user/0
[root@CentOS7 ~]# bash disk_check.sh 
USE1=15,use=,dev=,WRNING=80,USE=100
[root@CentOS7 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                   919504       0    919504   0% /dev
tmpfs                      931512       0    931512   0% /dev/shm
tmpfs                      931512   17984    913528   2% /run
tmpfs                      931512       0    931512   0% /sys/fs/cgroup
/dev/mapper/centos-root 104806400 4807440  99998960   5% /
/dev/sda1                 1038336 1038276        60 100% /boot
/dev/mapper/centos-data  52403200  227600  52175600   1% /data
tmpfs                      186304       0    186304   0% /run/user/0

 

 

VIII. select loop and menu

Format:

select NAME [in WORDS ... ;] do COMMANDS; done

select variable in list ;do
    Loop command
done

Description:

  • The select loop is mainly used to create menus. The menu items arranged in numerical order are displayed on the standard error, and the PS3 prompt is displayed for user input
  • The user enters a number in the menu list and executes the corresponding command
  • User input is saved in the built-in variable REPLY
  • select is an infinite loop, so use the break command to exit the loop or the exit command to terminate the script. You can also press Ctrl+c to exit the loop
  • select is often used in conjunction with case
  • Similar to the for loop, you can omit the in list and use the position parameter

Example:

[root@CentOS7 ~]# cat select.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     select.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
sum=0
PS3="Take your order, please(1-6): "
select MENU in Beijing roast duck Buddha jumping wall crayfish sheep scorpion hot pot order ends;do
case $REPLY in
1)
    echo $MENU The price is 100
    let sum+=100
    ;;
2)
    echo $MENU The price is 88
    let sum+=88
    ;;
3)
    echo $MENU The price is 66
    let sum+=66
    ;;
4)
    echo $MENU The price is 166
    let sum+=166
    ;;
5)
    echo $MENU The price is 200
    let sum+=200
    ;;
6)
    echo "End of order, exit"
    break
    ;;
*)
    echo "Input error, please select again"
    ;;
esac
done
echo "The total price is:$sum"
[root@CentOS7 ~]# bash select.sh 
1) Beijing Roast Duck
2) Steamed Abalone with Shark's Fin and Fish Maw in Broth
3) Crayfish
4) Lamb Spine Hot Pot
5) Hot Pot
6) End of order
 Take your order, please(1-6): 1
What is the price of Beijing roast duck 100
Take your order, please(1-6): 4
What is the price of sheep and scorpion 166
Take your order, please(1-6): 5
What's the price of hot pot 200
Take your order, please(1-6): 6
End of order, exit
 The total price is:466
[root@CentOS7 ~]#

 

Topics: shell