Keeping You in the Loop – Bash For, While, Until Loop Examples

Looping statements are used to force a program to repeatedly execute a statement. The executed statement is called the loop body.

Loops execute until the value of a controlling expression is 0. The controlling expression may be any scalar data type.

The shell language also provide several iteration or looping statements. In this article let us review the looping statements which bash provides using some examples.

Bash supports following three types of looping statement

  1. For loop
  2. While loop
  3. Until loop

This article is part of the on-going Bash Tutorial series.

Loops can be nested. Like any other programming language, bash also supports break statement to exit the current loop, and continue statement to resume the next iteration of the loop statement.

Bash For Loop – First Method

For loops are typically used when the number of iterations is known before entering the bash loop. Bash supports two kinds of for loop. The first form of bash for loop is:

for varname in list
	do
		commands ##Body of the loop
	done

In the above syntax:

  • for, in, do and done are keywords
  • List is any list which has list of items
  • varname is any Bash variable name.

In this form, the for statement executes the command enclosed in a body, once for each item in the list. The current item from the list will be stored in a variable “varname” each time through the loop. This varname can be processed in the body of the loop. This list can be a variable that contains several words separated by spaces. If list is missing in the for statement, then it takes the positional parameter that were passed into the shell.

Bash For Loop Example 1. Unzip all the Zip file

The following example finds the list of files which matches with “*.zip*” in the root directory, and creates a new directory in the same location where the zip file exists, and unzip the zip file content.

# cat zip_unzip.sh
#! /bin/bash
# Find files which has .zip
for file in `find /root -name "*.zip*" -type f`
do

# Skip the extension .zip
dirname=`echo ${file} | awk -F'.' '{print $1}'`

# Create the directory
mkdir $dirname

# Copy the zip file
cp ${file} ${dirname}
cd $dirname

# Unzip the zip file from newly created directory
unzip ${dirname}/$(echo ${file##/*/})
done
  • In this example find command returns the list of files, from which each file will be processed through a loop.
  • For each item, it creates the directory with the name of the zip file, and copies the zip file to the newly created directory and unzip the zip file from there.
  • The echo statement, echo ${file##/*/} gives you only the file name not the path.
# ./zip_unzip.sh
Archive:  /root/test2/test2.zip
 extracting: t1/p
 extracting: t1/q
 extracting: t1/r
 extracting: t1/s
 extracting: t1/t
 extracting: t1/u
 extracting: t1/v
Archive:  /root/test1/test1.zip
 extracting: t/a
 extracting: t/b
 extracting: t/c
 extracting: t/d
 extracting: t/e

Similar to the Bash loop, Awk also provides for loop and while loop as we discussed in our Awk While and For Loop article.

Bash For Loop – Second Method

The second form of for loop is similar to the for loop in ‘C’ programming language, which has three expression (initialization, condition and updation).

for (( expr1; expr2; expr3 ))
         do
		commands
         done
  • In the above bash for command syntax, before the first iteration, expr1 is evaluated. This is usually used to initialize variables for the loop.
  • All the statements between do and done is executed repeatedly until the value of expr2 is TRUE.
  • After each iteration of the loop, expr3 is evaluated. This is usually use to increment a loop counter.

The following example generates the n number of random numbers.

Bash For Example 2. Generate n random numbers

$ cat random.sh
#! /bin/bash

echo -e "How many random numbers you want to generate"
read max

for (( start = 1; start <= $max; start++ ))
do
        echo -e $RANDOM
done

$ ./random.sh
How many random numbers you want to generate
5
6119
27200
1998
12097
9181

In the above code snippet, the for loop generates the random number at max number of times. RANDOM is an internal bash function that returns a random integer at each invocation.

Bash While Loop

Another iteration statement offered by the shell programming language is the while statement.

Syntax:
while expression
do
	commands
done

In the above while loop syntax:

  • while, do, done are keywords
  • Expression is any expression which returns a scalar value
  • While statement causes a block of code to be executed while a provided conditional expression is true.

Bash While Example 3. Write contents into a file

The following example reads the data from the stdout and writes into a file.

$ cat writefile.sh
#! /bin/bash

echo -e "Enter absolute path of the file name you want to create"
read file
while read line
do
echo $line >> $file
done

$ sh writefile.sh
Enter absolute path of the file name you want to create
/tmp/a
while
for
until

$ cat /tmp/a
while
for
until

The above example, reads the filename from the user, and reads the lines of data from stdin and appends each line to a given filename. When EOF enters, read will fail, so the loop ends there.

If you are writing lot of bash scripts, you can use Vim editor as a Bash IDE using the Vim bash-support plugin as we discussed earlier.

Bash While Example 4. Read the contents of a file

In the previous example, it reads the data from stdout and write it into a file. In this example, it reads the file
content and write it into a stdout.

$ cat read.sh
#! /bin/bash
echo -e "Enter absolute path of the file name you want to read"
read file
exec <$file # redirects stdin to a file
while read line
do
echo $line
done

$ ./read.sh

Enter absolute path of the file name you want to read
/tmp/a
while
for
until

In this example, it gets the filename to read, and using exec it redirects stdin to a file. From that point on, all stdin comes from that file, rather than from keyboard. read command reads the line from stdin, so while loop reads the stdin, till EOF occurs.

Bash Until Loop

The until statement is very similar in syntax and function to the while statement. The only real difference between the two is that the until statement executes its code block while its conditional expression is false, and the while statement executes its code block while its conditional expression is true.

syntax:

until expression
	do
	   commands #body of the loop
	done

In the above bash until syntax:
where until, do, done are keywords
expression any conditional expression

Bash Until Example 5. Monitor the logfile

This example monitors the size of the logfile, once the logfile size reaches 2000bytes, it takes the copy of that logfile.

$ cat monitor.sh

file=/tmp/logfile
until [ $(ls -l $file | awk '{print $5}') -gt 2000 ]
        do
            echo "Sleeping for next 5 seconds"
            sleep 5
        done
date=`date +%s`
cp $file "$file-"$date.bak

$ ./monitor.sh
Sleeping for next 5 seconds
Sleeping for next 5 seconds

$ ls -l /tmp/logfile*
-rw-r--r-- 1 sss sss      2010 Jun 24 12:29 logfile
-rw-r--r-- 1 sss sss      2005 Jun 24 16:09 logfile-1277474574.bak

The until statement continues to execute the body of the loop, till the condition becomes true. In this example condition is size of the file greater than 2000 bytes, so it copies the file once it reaches the 2000 bytes.

Also, make sure to refer to our earlier Bash Array examples.

Bash Until Example 6. Waiting for the Machine to come up

This example is used to wait till the machine comes up before doing a ssh to that machine. The until loop statement ends only when the ping gives the responses.

$ cat mac_wait.sh
#! /bin/bash

read -p "Enter IP Address:" ipadd
echo $ipadd
until ping -c 1 $ipadd
do
        sleep 60;
done
ssh $ipadd

$./mac_wait.sh
Enter IP Address:192.143.2.10
PING 192.143.2.10 (192.143.2.10) 56(84) bytes of data.

--- 192.143.2.10 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

PING 192.143.2.10 (192.143.2.10) 56(84) bytes of data.
64 bytes from 192.143.2.10: icmp_seq=1 ttl=64 time=0.059 ms

--- 192.143.2.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.059/0.059/0.059/0.000 ms
The authenticity of host '192.143.2.10 (192.143.2.10)' can't be established.
Are you sure you want to continue connecting (yes/no)? yes

Until loop is quite useful at the command line, as a way of waiting for certain events to occur.

<think>好的,用户让我设计一个记录最喜欢的运动队得分统计的E-R图,需要存储比赛、每场比赛的得分、每场比赛的球员以及每个球员在每场比赛中的得分统计数据。首先,我需要确定核心实体。通常运动队统计会有比赛、球队、球员这些实体,但用户特别提到的是“你最喜欢的运动队”,所以可能只需要一个球队实体,还是需要考虑对手球队呢? 用户提到要存储“scores in each match”,所以每场比赛应该有主队和客队的得分,或者如果是单队统计的话,可能需要记录对手的信息。比如,比赛实体可能需要包含对手球队名称、比赛日期、地点,以及主队和客队的得分。但用户可能只关心自己支持的球队的数据,所以可能需要将比赛设计为包含对手球队、比赛日期、地点、本方得分和对手得分。 然后是球员实体,每个球员属于一个球队,但这里可能用户只关注自己的球队的球员,所以球员实体应该包括球员ID、姓名、位置等属性。接下来是球员在每场比赛中的得分统计,这应该是一个联系实体,因为同一个球员可以参加多场比赛,每场比赛有不同的统计。所以需要有一个“参赛”或“表现”联系集,连接球员和比赛,并记录得分、篮板、助攻等数据。 另外,用户提到“individual player scoring statistics for each match”,所以每个球员每场比赛的详细数据,可能需要多个属性,比如得分、助攻、篮板等。这时候需要考虑是否将这些作为属性放在联系集中,或者是否需要单独的统计实体。但通常这种情况会使用联系集来包含这些属性。 比赛和球队之间的关系可能需要考虑主队和客队,但用户可能只需要记录自己球队的比赛,所以比赛实体中的对手可以作为属性。或者是否需要另一个球队实体来代表对手?如果对手信息比较简单,可能作为比赛的属性更合适,但如果需要更多对手球队的详细信息,可能需要单独的球队实体。 主键方面,比赛可以用比赛ID,球员用球员ID,球队用球队ID。参赛联系集的主键可能是球员ID和比赛ID的组合。比赛和球队之间的关系可能需要考虑球队参加比赛的情况,但用户的需求可能更关注自己球队的比赛,所以可能不需要关联到球队实体,而是直接在比赛中记录对手信息。 需要确认是否有必要将球队作为实体,或者因为用户只关注一个球队,球队可以作为球员的属性。例如,每个球员属于该球队,而比赛则是该球队与其他对手的比赛。这种情况下,球队实体可能只需要一个,存储球队的基本信息,而比赛中的对手球队名称可以作为属性,而不需要单独的实体。 总结,核心实体包括比赛、球员,可能还有球队。联系集包括球员参赛(连接球员和比赛,记录统计数据)。比赛需要记录对手、时间、地点、得分等。可能不需要对手球队作为实体,除非需要存储更多对手的信息。 另外,得分可能需要分为球队得分和球员得分。每场比赛的球队得分在比赛实体中,而球员的得分在参赛联系集中。需要确保E-R图中的关系和属性正确分配,主键和外键正确连接。 可能的结构:球队实体(球队ID,名称,其他属性),球员实体(球员ID,姓名,位置,球队ID外键),比赛实体(比赛ID,日期,地点,对手名称,本方得分,对手得分),参赛联系集(球员ID,比赛ID,得分,篮板,助攻等)。 这样,球员和比赛之间的多对多关系通过参赛联系集表示,每个参赛记录包含该球员在该场比赛中的统计。球队和球员之间是一对多关系,一个球队有多个球员。比赛实体独立,记录每场比赛的总体信息。 需要检查是否有遗漏的实体或关系,比如是否需要教练、赛季信息等,但用户需求中没有提到,所以可能不需要。确保所有用户提到的要素都被涵盖:比赛、比赛得分、球员参与情况、球员个体统计。 最终,绘制E-R图时,用矩形表示实体,菱形表示关系,连线标注基数。例如,球员和参赛之间是1对多,因为一个球员可以参加多场比赛,每场比赛有多个球员参赛。比赛和参赛之间也是1对多,每场比赛有多个参赛记录,每个参赛记录属于一场比赛。球队和球员之间是1对多。比赛中的对手可能作为属性,或者如果对手是另一个球队实体,则需要另一个实体,但根据用户描述,可能不需要。这样设计应该能满足用户需求。</think>--- ### **体育队伍得分统计系统的E-R图设计** --- #### **1. 核心实体与属性** | **实体** | **属性** | **主键** | |----------------|-------------------------------------------------------------------------|-------------------| | **球队** | 球队ID, 球队名称, 所在地, 成立年份 | 球队ID | | **球员** | 球员ID, 姓名, 位置(如前锋/后卫), 身高, 体重, 加入日期 | 球员ID | | **比赛** | 比赛ID, 比赛日期, 比赛地点, 对手名称, 本方得分, 对手得分 | 比赛ID | | **球员表现** | 表现ID(可选), 得分, 助攻, 篮板, 抢断, 上场时间(分钟) | (球员ID + 比赛ID) | --- #### **2. 实体间关系与基数** 1. **球队与球员(1:N)** - **关系描述**:一支球队包含 **多名球员**,每个球员仅属于 **一支球队**。 - **联系集**:`隶属于` 2. **比赛与球队(1:N)** - **关系描述**:一支球队参与 **多场比赛**,每场比赛记录 **本方球队与对手球队的得分**。 - **设计说明**: - 对手信息简化为比赛的属性(对手名称、对手得分),若需详细管理对手球队,可扩展为独立实体。 3. **球员与比赛(M:N)** - **关系描述**:一个球员可参与 **多场比赛**,每场比赛有 **多名球员** 的统计数据。 - **联系集**:`参赛表现` - **联系集属性**:得分、助攻、篮板、抢断、上场时间。 --- #### **3. E-R 图示意** ```plaintext +--------+ 隶属于 (1:N) +--------+ | 球队 | <-----------------------> | 球员 | +--------+ +--------+ | | | 参与 (1:N) | 参赛表现 (M:N) | | +--------+ +--------+ | 比赛 | <-----------------------> | 球员表现 | +--------+ +--------+ ``` --- #### **4. 关键设计说明** 1. **球员表现的多维记录**: - 通过 `参赛表现` 联系集存储每场比赛中球员的详细数据(得分、助攻等),主键为复合键(球员ID + 比赛ID)。 - 示例:球员A(ID: P001)在比赛M001中得25分、10助攻。 2. **比赛的双向得分**: - 比赛实体直接记录本方得分与对手得分,避免复杂的外键关联。 - 若需追踪对手球队历史,可将“对手名称”升级为独立实体 `对手球队`,并与比赛建立关系。 3. **扩展性**: - 可添加 `赛季` 实体关联比赛,支持按赛季统计; - 可添加 `教练` 实体关联球队,管理教练信息。 --- #### **5. 数据示例** - **球队**:球队ID=T01,名称=“火箭队”,所在地=“休斯顿”。 - **球员**:球员ID=P01,姓名=“张三”,位置=“前锋”。 - **比赛**:比赛ID=M01,日期=2023-05-01,对手=“湖人队”,本方得分=110,对手得分=105。 - **球员表现**:球员P01在比赛M01中得分=28,助攻=8,篮板=12。 --- 此设计可高效追踪球队比赛历史、球员单场及累计数据,适用于篮球、足球等团队运动的统计分析需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值