Loop

Bash provides three loop syntaxes for, while and until.

while loop

The while loop has a judgment condition. As long as the condition is met, the specified statement will be executed continuously in a loop.

while condition; do
  commands
done

In the above code, as long as the condition condition is met, the command commands will be executed. Then, judge whether the condition condition is satisfied again, and it will continue to execute as long as it is satisfied. Only if the conditions are not met, the loop will exit.

The loop condition condition can use the test command, which is consistent with the writing of the judgment condition of the if structure.

#!/bin/bash

number=0
while [ "$number" -lt 10 ]; do
  echo "Number = $number"
  number=$((number + 1))
done

In the above example, as long as the variable $number is less than 10, it will continue to increase by 1 until $number is equal to 10, and then exit the loop.

The keyword do can not be on the same line as while, in which case there is no need to use a semicolon to separate the two.

while true
do
  echo 'Hi, while looping ...';
done

The above example will loop indefinitely, you can press Ctrl + c to stop.

It is also possible to write the while loop in one line.

$ while true; do echo 'Hi, while looping ...'; done

The condition part of while can also be to execute a command.

$ while echo 'ECHO'; do echo 'Hi, while looping ...'; done

In the above example, the judgment condition is echo'ECHO'. Since this command is always executed successfully, the above command will generate an infinite loop.

The condition part of while can execute any number of commands, but the authenticity of the execution result depends only on the execution result of the last command.

$ while true; false; do echo 'Hi, looping ...'; done

After the above code runs, there will be no output, because the last command of while is false.

until loop

The until loop is exactly the opposite of the while loop. As long as the judgment condition is not met (the judgment condition fails), the specified statement is executed continuously in a loop. Once the judgment conditions are met, the loop is exited.

until condition; do
  commands
done

The keyword do can not be written on the same line as until, and there is no need to separate the two with a semicolon.

until condition
do
  commands
done

Below is an example.

$ until false; do echo 'Hi, until looping ...'; done
Hi, until looping ...
Hi, until looping ...
Hi, until looping ...
^C

In the above code, the part of until is always false, which causes the command to run indefinitely and must be terminated by pressing Ctrl + c.

#!/bin/bash

number=0
until [ "$number" -ge 10 ]; do
  echo "Number = $number"
  number=$((number + 1))
done

In the above example, as long as the variable number is less than 10, it will continue to increase by 1 until the number is greater than or equal to 10, and the loop is exited.

The condition part of until can also be a command, which means that it will try repeatedly before the command is executed successfully.

until cp $1 $2; do
  echo 'Attempt to copy failed. waiting...'
  sleep 5
done

The above example shows that as long as the command of cp $1 $2 is not executed successfully, it will try again after 5 seconds until it succeeds.

Any until loop can be converted to a while loop, as long as the condition is set to negative. The above example can be rewritten as follows.

while ! cp $1 $2; do
  echo 'Attempt to copy failed. waiting...'
  sleep 5
done

Generally speaking, until is used less frequently, and while can be used uniformly.

for...in loop

The for...in loop is used to traverse each item in the list.

for variable in list
do
  commands
done

In the above grammar, the for loop will take one item from the list list in turn, as a variable variable, and then process it in the loop body.

The keyword do can be written on the same line as for, separated by a semicolon.

for variable in list; do
  commands
done

Below is an example.

#!/bin/bash

for i in word1 word2 word3; do
  echo $i
done

In the above example, word1 word2 word3 is a list of three words, and the variable i is equal to word1, word2, and word3 in turn. The command echo $i will be executed three times accordingly.

The list can be generated by wildcards.

for i in *.png; do
  ls -l $ i
done

In the above example, *.png will be replaced with all PNG image files in the current directory, and the variable i will be equal to each file in turn.

The list can also be generated by subcommands.

#!/bin/bash

count=0
for i in $(cat ~/.bash_profile); do
  count=$((count + 1))
  echo "Word $count ($i) contains $(echo -n $i | wc -c) characters"
done

In the above example, the cat ~/.bash_profile command will output the contents of the ~/.bash_profile file, and then by traversing each word, calculate how many words the file contains, and how many characters each word has.

The part of in list can be omitted. In this case, list is equal to all the parameters of the script $@ by default. However, for readability, it is better not to omit, refer to the following example.

for filename; do
  echo "$filename"
done

# Equivalent to

for filename in "$@" ; do
  echo "$filename"
done

The same is true in the function body. The for...in loop omits the part of in list, and list is equal to all the parameters of the function by default.

for loop

The for loop also supports the loop syntax of the C language.

for (( expression1; expression2; expression3 )); do
  commands
done

In the above code, expression1 is used to initialize the loop condition, expression2 is used to determine the condition for the end of the loop, and expression3 is executed at the end of each loop iteration to update the value.

Note that the loop condition is placed in double parentheses. In addition, when using variables in parentheses, there is no need to add a dollar sign $.

It is equivalent to the following while loop.

(( expression1 ))
while (( expression2 )); do
  commands
  (( expression3 ))
done

Below is an example.

for (( i=0; i<5; i=i+1 )); do
  echo $i
done

In the above code, the value of the initialization variable i is 0, and the condition of the loop execution is that i is less than 5. At the end of each loop iteration, the value of i is increased by 1.

All three statements in the conditional part of for can be omitted.

for ((;;))
do
  read var
  if [ "$var" = "." ]; then
    break
  be
done

The above script will repeatedly read the command line input until the user enters a dot (.) before jumping out of the loop.

break,continue

Bash provides two internal commands break and continue to break out of the loop inside the loop.

The break command immediately terminates the loop, and the program continues to execute the statements after the loop block, that is, the rest of the loop is no longer executed.

#!/bin/bash

for number in 1 2 3 4 5 6
do
  echo "number is $number"
  if [ "$number" = "3" ]; then
    break
  be
done

The above example will only print 3 rows of results. Once the variable $number is equal to 3, it will break out of the loop and will not continue execution.

The continue command immediately terminates the current cycle and begins to execute the next cycle.

#!/bin/bash

while read -p "What file do you want to test?" filename
do
  if [ ! -e "$filename" ]; then
    echo "The file does not exist."
    continue
  be

  echo "You entered a valid file.."
done

In the above example, as long as the file entered by the user does not exist, the continue command will take effect and directly enter the next round of loop (allowing the user to re-enter the file name) without executing the following print statements.

select structure

The select structure is mainly used to generate simple menus. Its syntax is basically the same as the for...in loop.

select name
[in list]
do
  commands
done

Bash will perform the following processing on select in sequence.

  1. select generates a menu, the content is each item in the list list, and there is a number in front of each item.
  2. Bash prompts the user to select an item and enter its number.
  3. After the user inputs, Bash will store the content of the item in the variable name, and store the item number in the environment variable REPLY. If the user does not input, press the Enter key, and Bash will re-output the menu for the user to choose.
  4. Execute the command body commands.
  5. After the execution is over, go back to the first step and repeat the process.

Below is an example.

#!/bin/bash
# select.sh

select brand in Samsung Sony iphone symphony Walton
do
  echo "You have chosen $brand"
done

Execute the above script, Bash will output a list of brands for users to choose.

$ ./select.sh
1) Samsung
2) Sony
3) iphone
4) symphony
5) Walton
#?

If the user does not enter the number, just press the Enter key. Bash will output this menu again until the user presses Ctrl + c to exit the execution.

select can be combined with case to execute different commands for different items.

#!/bin/bash

echo "Which Operating System do you like?"

select os in Ubuntu LinuxMint Windows8 Windows10 WindowsXP
do
  case $os in
    "Ubuntu"|"LinuxMint")
      echo "I also use $os."
    ;;
    "Windows8" | "Windows10" | "WindowsXP")
      echo "Why don't you try Linux?"
    ;;
    *)
      echo "Invalid entry."
      break
    ;;
  esac
done

In the above example, case executes different commands for different items selected by the user.