shell loop explanation and examples

Keywords: shell

 

1, Condition selection and judgment (if, case)

1.1 if statement usage and examples

When we need to judge in the script, we can use the if statement to implement it. The specific syntax is as follows:

  •    Single branch

    if judgment conditions; then

Branch code with true condition
  fi

  •    Double branch

if   Judgment conditions; then

Branch code with true condition

else

Branch code with false condition

fi

  •    Multi branch

if   Judgment condition 1; then

Branch code with true condition
elif   Judgment condition 2; then

Branch code with true condition
elif   Judgment condition 3; then

Branch code with true condition

else

The above conditions are false branch codes
fi

In multiple branches, the system will judge the conditions you write one by one. When you encounter the "true" condition for the first time, execute the branch, and then end the whole if statement.

Note: 1. if and fi appear in pairs

2. if statements can be nested.

Example:

1) Judge the size of two numbers

 
 1 #!/bin/bash
 2 #Define variables
 3 read -p "Please input the first num:" num1
 4 read -p "Please input the second num:" num2
 5 #Judge whether the number meets the standard
 6 if [[ $num1 =~ ^[0-9]+$ && $num2 =~ ^[0-9]+$ ]];then
 7 #    Judge the size of the two numbers and output the judgment result
 8     if [ $num1 -lt $num2 ];then
 9         echo "The num2 is biger than the num1"
10     elif [ $num1 -eq $num2 ];then
11         echo "Two numbers equal"
12     else 
13         echo "The num1 is biger than the num2"
14     fi
15 else
16     echo "Please enter the correct number"
17 fi
18 
19 #Delete variable
20 unset num1 num2
 

 

 

2) Write a script / root/bin/createuser.sh to realize the following functions: use a user name as a parameter. If the user with the specified parameter exists, it will be displayed; otherwise, it will be added; Displays the id number and other information of the added user

 
 1 #!/bin/bash
 2 #Define variables
 3 read -p "Please enter a user name:" name
 4 #Determine whether the user name exists
 5 if  `id $name &> /dev/null`;then
 6 #    If it exists, information such as ID will be output
 7 echo "User exists, user's ID The information is:`id $name`"
 8 else
 9 #    If it does not exist, add a user, set the password to random 8 digits, prompt to change the password when logging in next time, and display ID and other information at the same time
10 passwd=`cat /dev/urandom |tr -cd [:alpha:] |head -c8`
11 `useradd $name &> /dev/null`
12 `echo "$passwd" | passwd --stdin $name &> /dev/null`
13 echo "user name: $name password: $passwd" >> user.txt
14 `chage -d 0 $name`
15 echo "User added, user's ID The information is:`id $name` Password is: $passwd"
16 fi
17 
18 #Delete variable
19 unset name passwd
 

 

 

1.2 case usage and examples

When multiple condition matching is involved, it may be troublesome for us to use if. At this time, we can use case to write this script. The specific syntax of case is as follows:

case   Variable reference   in

PAT1)

Branch 1

;;

PAT2)

Branch 2

;;

...

*)

Default branch

;;

esac

Note: 1. After each branch of case, it ends with two "; (the last one can be omitted)

       2. case and esac appear in pairs

Example:

1) Write a script to prompt the user to enter information and judge whether the input is yes or no or other information.

 
 1 #!/bin/bash
 2 #Define variables
 3 read -p "Yue ma?(yes or no): " ANS 
 4 #Convert uppercase to lowercase in variables
 5 ans=`echo "$ANS" |tr [[:upper:]] [[:lower:]] `
 6 #Determine what the input information is and output the result
 7 case $ans in
 8 yes|y)
 9     echo "see you tonight"
10     ;;  
11 no|n)
12     echo "sorry,I have no time"
13     ;;  
14 *)
15     echo "what's your means?"
16     ;;  
17 esac
18 
19 #Delete variable
20 unset ANS ans
 

 

 

2) Write a script / root/bin/filetype.sh to judge the file path entered by the user and display its file type (normal, directory, link, other file types)

 
 1 #!/bin/bash
 2 read -p "Please enter a file path:" file
 3 #Determine whether the file exists
 4 `ls $file &> /dev/null`
 5 #If it exists, judge the file type and output it
 6 if [ $? -eq 0 ];then
 7     style=`ls -ld $file | head -c1`
 8     case $style in
 9     -)  
10         echo "This is an ordinary file"
11         ;;  
12     d)  
13         echo "This is a directory file"
14         ;;  
15     l)  
16         echo "This is a linked file"
17         ;;
18     *)
19         echo "This is another type of file"
20         ;;
21     esac
22 #If not, prompt and exit
23 else
24     echo "The file does not exist"
25     exit 2
26 fi
27 
28 #Delete variable
29 unset file style
 

 

 

2, Circular statement

     In our script, there must be repeated operations on a certain piece of code. At this time, we will use circular statements. In loop statements, there are entry conditions and exit conditions, and the number of cycles is also divided into known in advance and unknown in advance (known in advance means that we know the specific number of cycles, and unknown in advance means that we cycle when a certain condition is met, but the number is uncertain). Next, let's look at the usage of circular statements.

2.1 for loop

The execution mechanism of the for loop is: assign the element in the list to the "variable name" at one time; The loop body is executed once after each assignment; The loop ends until the elements in the list are exhausted. There are two basic Grammars:

1)for   Variable name   in   list  ; do

Circulatory body

done

The list generation method is as follows:

① Give a list directly

② Integer list:

(a){start...end}

(b)`seq start end`

③ Command to return to list

    $(COMMAND)

④ Use glob wildcards, such as:

      *.sh

⑤ Variable reference

$i,$*

2)for (( exp1; exp2; exp3 )); do

Circulatory body

done

    More clearly, it can be seen from the following figure:

 

 

Example:

1) Print 99 multiplication table

 
 1 #!/bin/bash
 2 #Judge whether the value of i is 1-9
 3 for i in {1..9};do
 4 #   Judge whether the value of j is 1-$i
 5 for j in `seq 1 $i`;do
 6 #       If yes, print the value of i*j
 7         echo -en "$i*$j = $[$i*$j]\t" 
 8     done
 9     echo
10 done
11 
12 #Delete variable
13 unset i j
 

 

 

2) Enter a positive integer n to calculate the sum of 1 +... + n

 
 1 #!/bin/bash
 2 #Define variables
 3 sum=0
 4 read -p "Please enter a positive integer:" num 
 5 #Determine whether num is a positive integer
 6 if [[ $num =~ ^[[:digit:]]+$ ]];then
 7 #   If yes, when i is in 1-$num, the sum value is output
 8     for i in `seq 1 $num`;do
 9         let sum+=$i    
10     done 
11         echo "sum=$sum"
12 #If not, prompt to output a positive integer
13 else 
14     echo "Please enter a positive integer!"
15 fi
16 
17 #Delete variable
18 unset i sum num
 

 

 

2.2 while loop

The while loop is slightly more complex than the for loop. The specific syntax is as follows:

while CONDITION; do

       Circulatory body

done

Note: 1. Entry CONDITION: CONDITION is true; Exit CONDITION: CONDITION is false.

       2. CONDITION is the cycle control CONDITION: make a judgment before entering the cycle; Judgment will be made again after each cycle; If the CONDITION is "true", a loop is executed; Terminate the loop knowing that the CONDITION test status is "false".

       3. CONDITION should generally have loop control variables; The value of this variable is constantly modified in the loop body.

Example:

1) Calculate the sum of all positive odd numbers within 100

 
 1 #!/bin/bash
 2 #Define variables
 3 i=1
 4 sum=0
 5 #When I < 100, execute the following statement
 6 while [ $i -le 100 ];do
 7 #When i is an odd number, sum=sum+I,i=i+1
 8     while [ $[i%2] -eq 1 ];do
 9         let sum+=$i
10         let i+=1 
11 done
12 #   When i is not an odd number, i=i+1
13     let i+=1
14 done
15 #Output results
16 echo "sum=$sum"
17 
18 #Delete variable
19 unset i sum
 

 

 

2.3 until cycle

    The syntax of until loop is similar to that of while, but the entry and exit conditions are just the opposite, so it is not often used, as long as we understand it. The specific syntax is as follows:

until CONDITION; do

    Circulatory body

done

Note: 1. Entry CONDITION: CONDITION is false; Exit CONDITION: CONDITION is true.

      2. do and done appear in pairs.

Example:

1) Cycle output 1-10

 
 1 #!/bin/bash
 2 #Define variables
 3 i=1
 4 #When I > 10, exit the cycle
 5 until [ $i -gt 10 ];do
 6 #   Output the value of i, i=i+1
 7     echo $i 
 8     let i+=1
 9 done
10 
11 #Delete variable
12 unset i 
 

 

 

2.4 select loop

    The select loop is mainly used to create menus. The menu items arranged in numerical order will be displayed on the standard error and PS3 prompt will be 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.

    The specific syntax of select is as follows:

select variable in list; do

    Loop command

done

Note: ① select is a wireless loop, so remember to exit the loop with the break command or terminate the script with the exit command. 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 location variable.

Example:

1) Generate a menu and display the selected price.

 
 1 #!/bin/bash
 2 #Define PS3 prompt
 3 PS3="Please choose the menu: "
 4 #Output menu
 5 select menu in yangroutang mifan hulatang jiaozi lamian huimian quit
 6 do
 7 #   Judgment selection
 8     case $REPLY in
 9     1|4)
10         echo "The price is 20"
11         ;;  
12     2|5)
13         echo "The price is 12"
14         ;;  
15     3|6)
16         echo "The price is 10"
17         ;;  
18     7)  
19         break
20         ;;  
21     *)  
22         echo "Choose error"
23         ;;  
24     esac
25 done
 

 

 

two point five   Cyclic small supplement

2.5.1   Loop control statement   continue&break

    Loop control statements are used in the loop body. There are two common control statements, continue and break. Next, let's look at the difference between the two:

The continue statement ends the current cycle and directly enters the next round of judgment; The innermost layer is the first layer.

The break statement ends the whole loop, and the innermost layer is layer 1.

Example:

1) Find the sum of (1 + 3 +... + 49 + 53 +... + 99)

 
 1 #Define variables
 2 sum=0
 3 for ((i=1;i<=100;i++));do
 4 #   When i is an odd number, continue
 5     if [ $[i%2] -eq 1 ];then
 6 #       When i=51, skip the loop
 7         if [ $i -eq 51 ];then
 8             continue
 9         fi  
10         let sum+=$i
11     fi  
12 done
13 echo "sum=$sum"
14 
15 #Delete variable
16 unset i sum
 

 

 

2) Find the sum of (1 + 3 +... + 49)

 
 1 #!/bin/bash
 2 #Define variables
 3 sum=0
 4 for ((i=1;i<=100;i++));do
 5 #   When i is an odd number, continue
 6     if [ $[i%2] -eq 1 ];then
 7 #       When i=51, jump out of the whole cycle
 8         if [ $i -eq 51 ];then
 9             continue
10         fi  
11         let sum+=$i
12     fi  
13 done
14 echo "sum=$sum"
15 
16 #Delete variable
17 unset i sum
 

 

 

2.5.2   Loop control command shift

    The position parameter can be shifted to the left with the shift command. For example, shift 3 means that the original $4 is now $1, the original $5 is now $2, etc., the original $1, $2, $3 is discarded, and $0 is not moved. The shift command without parameters is equivalent to shift 1.

    We know that the number of location variables or command-line parameters must be determined, or when the shell program does not know the number, all parameters can be assigned to the variable $*. When the user requires the shell to process the parameters one by one without knowing the number of location variables, that is, $2 after $1, etc. Before the shift command is executed, the value of variable $1 is unavailable after the shift command is executed.

Example:

1) Test the shift command

1 #!/bin/bash
2 until [ $# -eq 0 ];do
3     echo "The first argument is:$1,The number of arguments is:$#"
4     shift
5 done

 

 

2.5.3   Signal capture trap

    Trap is a shell built-in command, which is used to specify how signals are processed in scripts. For example, pressing Ctrl+C will terminate the execution of the script. In fact, the system sends a SIGINT signal to the script process. The default processing method of SIGINT signal is to EXIT the program. If you want to EXIT the program without Ctrl+C, you have to use the trap command to specify the processing method of SIGINT. The trap command not only processes Linux signals, but also specifies the processing methods for script EXIT (EXIT), debugging (DEBUG), error (ERR), RETURN, etc.

    The basic format syntax is as follows:

  •    trap 'trigger instruction'   signal

    After receiving the specified signal from the system, the custom process will execute the trigger instruction instead of the original operation

  •         trap ‘’   signal

    Operation of ignoring signals

  •    trap ‘-’   signal

    Operation of restoring the original signal

  •        trap -p

    List the operations of custom signals, that is, prompt what trap operations are currently used.

Note: ① signal representation method: it can be complete signal / abbreviation / number (specific contents can be queried through kill -l)

② Signal 9, forced kill, unable to capture.

Example:

1) Print 0-9, ctrl+c termination is invalid

 
1 #!/bin/bash
2 #Set signal capture
3 trap 'echo press ctrl+c' 2
4 for ((i=0;i<10;i++));do
5     sleep 1
6     echo $i
7 done
 

 


2) When printing 0-9, ctrl+c cannot be terminated before 3, and can be terminated after 3

 
 1 #!/bin/bash
 2 #Set signal capture
 3 trap '' 2
 4 trap -p
 5 for ((i=0;i<3;i++));do
 6     sleep 1
 7     echo $i
 8 done
 9 trap '-' SIGINT
10 for ((i=3;i<10;i++));do
11     sleep 1
12     echo $i
13 done
 

 


2.5.4   Create an infinite loop

    In our shell script, you can create an endless loop. The specific settings are as follows:

   while true;do

      Circulatory body

   done

 

2.5.5   Execute parallel commands in loop statements

    When we need to execute a command many times in the script, we can set it to parallel execution, which can greatly improve the running speed of the script, but there are also disadvantages. Parallel execution is equivalent to opening many sub shell s to execute together. The running speed is up, but the consumption of resources is also increased.

    Specific usage examples are as follows:

    for name in   List; do

     {

         Circulatory body

}$

   done

   wait

Example:

1) Search for the ip address of up in the network segment with the specified ip (subnet mask 24)

 
 1 #!/bin/bash
 2 #Define variables
 3 read -p "Please input network (eg:172.17.0.1): " net echo $net |egrep -o "\<(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"
 4 #Judge whether the network segment meets the specification
 5 [ $? -eq 0 ] || ( echo "input error";exit 10 )
 6 #Determine which IP S in the network segment can be ping ed and executed in parallel
 7 IP=`echo $net |egrep -o "^([0-9]{1,3}\.){3}"`
 8 for i in {1..254};do
 9      {   
10          ping -c 1 -w 1 $IP$i &> /dev/null && \
11          echo "$IP$i is up" 
12      }&  
13 done
14 wait
15  
16 #Delete variable
17 unset net IP i
 

 

 

3, Small supplement

       After introducing so many grammars, let's play some fun ~ here are some interesting scripts to share with you

1) Print isosceles triangle (with flashing)

 
 1 #!/bin/bash
 2 #num = total line number i = the number of lines j = * number k = number of spaces
 3 read -p "Please enter a number:" num 
 4 for i in `seq 1 $num`;do
 5     for k in `seq 1 $[$num-$i]`; do
 6         echo -n " "
 7     done
 8     for j in `seq 1 $[2*$i-1]`;do
 9         if [ $j -eq 1 ] || [ $j -eq $[2*$i-1] ] || [ $i -eq $num ];then
10             color=$[RANDOM%5+31]
11             echo -en "\033[1;$color;5m*\033[0m"
12         else
13             echo -n "*"
14         fi  
15     done
16     echo
17 done
18 
19 #Delete variable
20 unset num i j k color
 

          You can try the specific effect yourself, which is the effect of the following two pictures:

 


2) Print chess board

 
 1 #!/bin/bash
 2 #Define variables
 3 color_1="\033[1;44m  \033[0m"
 4 color_2="\033[1;45m  \033[0m"
 5 for (( i=1;$i <=8;i++ ));do
 6     for (( j=1;$j <=8;j++ ));do
 7         if [ $[$i%2] == 1 ] && [ $[$j%2] == 1 ];then
 8             echo -en "$color_1$color_2"
 9         elif [ $[$i%2] == 0 ] && [ $[$j%2] == 0 ];then
10             echo -en "$color_2$color_1"
11         fi  
12     done
13     echo
14 done
15 
16 #Delete variable
17 unset color_1 color_2 i j
 

 

 
 

Posted by kumar_ldh on Wed, 10 Nov 2021 14:42:35 -0800