Bash 基础知识系列 #8：For、While 和 Until 循环
Bash 脚本
![](/data/attachment/album/202308/21/100731qmt2cmxnyub9xm62.jpg)



> 
> 在 Bash 基础知识系列的倒数第二章节，学习 `for`、`while` 和 `until` 循环。
> 
> 
> 


循环是任何编程语言中的一个强大功能。如果你还不知道，循环其实是一种根据某些条件重复代码的方式。


例如，想象一下你需要打印从 1 到 10 的数字。你可以使用 `echo` 命令写十次，但那太原始了。你使用一个循环，在 3 到 4 行代码内，就能完成。


这是我能想到的最简单的例子。我将在讨论 Bash 循环时，分享一些实际有用的例子。


在 Bash 中有三种类型的循环：


* `for`
* `while`
* `until`


我将在教程中展示所有三种类型的循环。让我们从最常见的一种开始。


### Bash 中的 For 循环


以下是 Bash 中的 `for` 循环语法：



```
for arg in LIST; do
    commands
done

```

这里的 `LIST` 可能是一个数组或者一个项目列表。[括号扩展](https://linuxhandbook.com/brace-expansion/?ref=itsfoss.com) 也是进行循环的常用手段。


考虑一下我在开始提到的最简单的场景。让我们使用 `for` 循环打印从 1 到 10 的数字：



```
#!/bin/bash

for num in {1..10}; do
    echo $num
done

```

如果你运行它，你应该会看到像这样的输出：



```
$ ./for-loop.sh
1
2
3
4
5
6
7
8
9
10

```

你也可以使用 `for num in 1 2 3 4 5 6 7 8 9 10; do` ，但是使用括号扩展使得代码看起来更短且更智能。


`{..}` 是用于扩展模式的。你使用 `{d..h}` ，它等同于 `d e f g h` 。关于括号扩展的更多信息，可以在这篇文章中找到。



> 
> **[在 Bash 中使用括号扩展](https://linuxhandbook.com/brace-expansion/?ref=itsfoss.com)**
> 
> 
> 



> 
> ? 如果你熟悉 C 语言编程，你可能会喜欢在 bash 中使用 C 风格的 for 循环：
> 
> 
> 
> ```
> for ((i = 0 ; i < 10 ; i++)); do
>   echo $i
> done
> 
> ```
> 
> 


让我们看另一个例子，显示 [Bash 数组](https://itsfoss.com/bash-arrays/) 的所有内容：



```
#!/bin/bash

distros=(Ubuntu Fedora Debian Alpine)

for i in "${distros[@]}"; do
    echo $i
done

```

如果你运行脚本，它将显示数组中定义的所有发行版：



```
Ubuntu
Fedora
Debian
Alpine

```

### Bash 中的 While 循环


`while` 循环测试一个条件，然后只要条件为真，就继续循环。



```
while [ condition ]; do
    commands
done

```

如果你考虑前一个例子，它可以使用 `while` 循环进行重写：



```
#!/bin/bash

num=1
while [ $num -le 10 ]; do
    echo $num
    num=$(($num+1))
done

```

如你所见，你首先需要将变量 `num` 定义为 1，然后在循环体内，你增加 `num` 的值。只要 `num` 小于或等于 10，while 循环就会检查条件并运行脚本。


因此，现在运行脚本将会显示出和之前 `for` 循环中看到的完全相同的结果。



```
1
2
3
4
5
6
7
8
9
10

```

让我们看另一个例子。这是一个 [Bash 脚本，它接受一个数字作为参数](https://itsfoss.com/bash-pass-arguments/) 并显示该表。



```
#!/bin/bash

echo "Table for $1 is:"
index=1
while [ $index -le 10 ]; do
    echo $(($1*$index))
    index=$(($index+1))
done

```

如果你对 `$1` 的使用感到困惑，它代表传递给脚本的第一个参数。更多的细节可以参考这个系列的 [第三章](https://itsfoss.com/bash-pass-arguments/)。


如果你运行这个脚本，它应该会显示以下的输出：



```
$ ./table.sh 2
Table for 2 is:
2
4
6
8
10
12
14
16
18
20

```

### Bash 中的 Until 循环


这是一个使用较少的循环格式。它的行为和 `while` 循环类似。这里的区别是，循环运行直到它检查的条件为真为止。意味着为了在循环中执行代码，`[ ]` 中的条件必须为假。


我马上会解释一下。让我们先看一下它的语法。



```
until [ condition ]; do
    commands
done

```

现在，如果我要使用相同的示例，即使用 `until` 循环打印从 1 到 10 的数字，它看起来会是这样：



```
#!/bin/bash

num=1
until [ $num -gt 10 ]; do
    echo $num
    num=$(($num+1))
done

```

区别在于条件；其余部分保持不变。


* 当变量 `num` 小于或等于 10 时，while 循环就会运行。`[ ]` 中的条件必须为真，循环才会执行。
* 知道变量 `num` 变得大于 10 时，until 循环才会运行。`[ ]` 中的条件必须为假，循环才会执行。


这都是做同样事情的两种不同方式。`while` 更受欢迎，因为你会在大多数编程语言中找到类似 `while` 的循环语法。


### ?️ 练习时间


那是有趣的。现在是做一些练习的时候了。


**练习 1**：编写一个脚本，该脚本接受一个数字作为参数并打印其表格。如果脚本在没有参数的情况下运行，你的脚本还应显示一个消息。


**预期输出**：



```
$: ./table.sh
You forgot to enter a number

$: ./table.sh 3
3
6
9
12
15
18
21
24
27
30

```

**练习 2** : 编写一个脚本，列出目录 `/var` 中的所有文件。


**提示** : 对于循环，使用 `/var/*` 作为 “列表”。


Bash 基础知识系列即将结束。作为该系列的最后一章，你将在下周学习在 Bash 脚本中使用函数。敬请期待。


*（题图：MJ/945241d6-6a73-432c-9bcd-e0948b3fadc0）*




---


via: <https://itsfoss.com/bash-loops/>


作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[lujun9972](https://github.com/lujun9972) 译者：ChatGPT 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
# Chapter #8: For, While and Until Loops

In the penultimate chapter of the Bash Basics series, learn about for, while and until loops.

Loops are a powerful feature in any programming language. If you do not know already, the loops are a way to repeat the code based on certain criteria.

For example, imagine that you have to print the numbers from 1 to 10. You can write the echo command ten times but that's very primitive. You use a loop and in 3-4 lines of code, it can be done.

That's the simplest of the examples I could think of. I am going to share actual useful examples while I discuss the bash loops with you.

There are three types of loops in Bash:

- For
- While
- Until

I'll show all three kinds of looping in the tutorial. Let's start with the most common one.

## For loop in bash

Here's the syntax for 'for loop' in bash:

```
for arg in LIST; do
commands
done
```


The LIST here could be an array or a list of items. [Brace expansions](https://linuxhandbook.com/brace-expansion/) are also popular for looping.

Take the simplest scenario I mentioned in the beginning. Let's print numbers from 1 to 10 using for loop:

```
#!/bin/bash
for num in {1..10}; do
echo $num
done
```


If you run it, you should see an output like this:

```
abhishek@itsfoss:~/bash_scripts$ ./for-loop.sh
1
2
3
4
5
6
7
8
9
10
```


You could have also used `for num in 1 2 3 4 5 6 7 8 9 10; do`

but using the brace expansion makes the code look shorter and smarter.

`{..}`

is used for expanding on a pattern. You use `{d..h}`

and it is equivalent to `d e f g h`

. More on brace expansion can be found in this article.

[Using Brace Expansion in Bash ShellBrace expansion in the bash shell is a lesser known but an awesome feature. Learn about using them like a Pro Linux user with practical examples.](https://linuxhandbook.com/brace-expansion/)![](https://linuxhandbook.com/content/images/2022/11/bash-expansion-in-linux.png)


![](https://linuxhandbook.com/content/images/2022/11/bash-expansion-in-linux.png)

for ((i = 0 ; i < 10 ; i++)); do

echo $i

done

Let's see another example that displays all the contents of an [array in bash](https://itsfoss.com/bash-arrays/):

```
#!/bin/bash
distros=(Ubuntu Fedora Debian Alpine)
for i in "${distros[@]}"; do
echo $i
done
```


If you run the script, it will display all the distros defined in the array:

```
Ubuntu
Fedora
Debian
Alpine
```


## While loop in bash

The while loop tests a condition and then keeps on looping as long as the condition is true.

```
while [ condition ]; do
commands
done
```


If you take the previous example, it can be rewritten using the while loop like this:

```
#!/bin/bash
num=1
while [ $num -le 10 ]; do
echo $num
num=$(($num+1))
done
```


As you can see, you had to define the variable `num`

to 1 first and then in the loop body, you increase the value of `num`

by 1. The while loop checks the condition and runs it as long as `num`

is less than or equal to 10.

Thus, running the script now will show the exact result you saw earlier with for loop.

```
1
2
3
4
5
6
7
8
9
10
```


Let's see another example. Here's a [bash script that takes a number as an argument](https://itsfoss.com/bash-pass-arguments/) and displays its table.

```
#!/bin/bash
echo "Table for $1 is:"
index=1
while [ $index -le 10 ]; do
echo $(($1*$index))
index=$(($index+1))
done
```


If you are confused about the use of $1, it represents the first argument passed to the script. Check out [chapter 3 of this series](https://itsfoss.com/bash-pass-arguments/) for more details.

If you run the script, it should show this output:

```
abhishek@itsfoss:~/bash_scripts$ ./table.sh 2
Table for 2 is:
2
4
6
8
10
12
14
16
18
20
```


## Until loop in bash

This is the lesser-used loop format. It behaves similarly to the while loop. The difference here is that the loop runs until the condition it checks is true. This means for the code in the loop to execute, the condition in `[ ]`

has to be false.

I'll explain it in a bit. Let's see its syntax first.

```
until [ condition ]; do
commands
done
```


Now, if I have to use the same example of printing numbers from 1 to 10 using until loop, it would look like this:

```
#!/bin/bash
num=1
until [ $num -gt 10 ]; do
echo $num
num=$(($num+1))
done
```


The difference is in the condition; the rest remains the same.

- The while loop ran while the variable
`num`

was less than or equal to 10. The condition in`[ ]`

has to be true for the loop to execute. - The until loop runs until the variable
`num`

becomes greater than 10. The condition in `[ ]` has to be false for the loop to execute.

Both are different ways of doing the same thing. While is more popular as you'll find a while loop equivalent in most programming languages.

## 🏋️ Exercise time

That was fun. Time to do some exercise now.

**Exercise 1**: Write a script that takes a number as an argument and prints its table. Your script should also show a message if the script is run without an argument.

**Expected output**:

```
$: ./table.sh
You forgot to enter a number
$: ./table.sh 3
3
6
9
12
15
18
21
24
27
30
```


**Exercise 2**: Write a script that lists all the files in the directory /var

**Hint**: Use for loop with /var/* as the 'list'.

You can discuss your answers in this dedicated thread in the Community:

[Practice Exercise in Bash Basics Series #8: For, While and Until LoopsIf you are following the Bash Basics series on It’s FOSS, you can submit and discuss the answers to the exercise at the end of the chapter: Fellow experienced members are encouraged to provide their feedback to new members. Do note that there could be more than one answer to a given problem.](https://itsfoss.community/t/practice-exercise-in-bash-basics-series-8-for-while-and-until-loops/10960)![](https://itsfoss.community/uploads/default/original/1X/f274f9749e3fd8b4d6fbae1cf90c5c186d2f699c.png)


![](https://itsfoss.community/uploads/default/original/1X/f274f9749e3fd8b4d6fbae1cf90c5c186d2f699c.png)

The bash basics series is coming to an end. As the final chapter in the series, you'll learn to use functions in bash scripting next week. Stay tuned.