在 awk 编程中有各种各样的流程控制语句,其中包括:
if-else 语句
for 语句
while 语句
do-while 语句
break 语句
continue 语句
next 语句
nextfile 语句
exit 语句
- if-else 语句
如你想的那样。if 语句的语法类似于 shell 中的 if 语句:
if (条件 1) { 动作 1 } else { 动作 2 }
在上述语法中,条件 1 和条件 2 是 awk 表达式,而动作 1 和动作 2 是当各自的条件得到满足时所执行的 awk 命令。
当条件 1 满足时,意味着它为真,那么动作 1 被执行并退出 if 语句,否则动作 2 被执行。
if 语句还能扩展为如下的 if-else_if-else 语句:if (条件 1){ 动作 1 } else if (条件 2){ 动作 2 } else{ 动作 3 }
对于上面的形式,如果条件 1 为真,那么动作 1 被执行并退出 if 语句,否则条件 2 被求值且如果值为真,那么动作 2 被执行并退出 if 语句。然而,当条件 2 为假时,那么动作 3 被执行并退出 if 语句。
这是在使用 if 语句的一个实例,我们有一个用户和他们年龄的列表,存储在文件 users.txt 中。
我们要打印一个清单,显示用户的名称和用户的年龄是否小于或超过 25 岁。aaronkilik@tecMint ~ $ cat users.txt Sarah L 35 F Aaron Kili 40 M John Doo 20 M Kili Seth 49 M
我们可以写一个简短的 shell 脚本来执行上文中我们的工作,这是脚本的内容:
#!/bin/bash awk ' { if ( $3 <= 25 ){ print "User",$1,$2,"is less than 25 years old." ; } else { print "User",$1,$2,"is more than 25 years old" ; } }' ~/users.txt
然后保存文件并退出,按如下方式使脚本可执行并运行它:
$ chmod +x test.sh $ ./test.sh
输出样例
User Sarah L is more than 25 years old User Aaron Kili is more than 25 years old User John Doo is less than 25 years old. User Kili Seth is more than 25 years old
- for 语句
如果你想在一个循环中执行一些 awk 命令,那么 for 语句为你提供一个做这个的合适方式,格式如下:
for ( 计数器的初始化 ; 测试条件 ; 计数器增加 ){ 动作 }
这里,该方法是通过一个计数器来控制循环执行来定义的,首先你需要初始化这个计数器,然后针对测试条件运行它,如果它为真,执行这些动作并最终增加这个计数器。当计数器不满足条件时,循环终止。
在我们想要打印数字0到10时,以下awk命令显示for语句是如何工作的:$ awk 'BEGIN{ for(counter=0;counter<=10;counter++){ print counter} }'
输出样例
0 1 2 3 4 5 6 7 8 9 10
- while 语句
while 语句的传统语法如下: while ( 条件 ) { 动作 }
这个条件是一个 awk 表达式而动作是当条件为真时被执行的 awk 命令。 下面是一个说明使用 while 语句来打印数字 0 到 10 的脚本:
#!/bin/bash awk ' BEGIN{ counter=0; while(counter<=10){ print counter; counter+=1; } }'
保存文件并使脚本可执行,然后运行它:
$ chmod +x test.sh $ ./test.sh
输出样例
0 1 2 3 4 5 6 7 8 9 10
- do while 语句
它是上文中 while 语句的一个变型,具有以下语法:
do { 动作 } while (条件)
这轻微的区别在于,在 do while 语句下,awk 的命令在求值条件之前执行。使用上文 while 语句的例子,我们可以通过按如下所述修改 test.sh 脚本中的 awk 命令来说明 do while 语句的用法:
#!/bin/bash awk ' BEGIN{ counter=0; do{ print counter; counter+=1; } while (counter<=10) }'
修改脚本之后,保存文件并退出。按如下方式使脚本可执行并执行它:
$ chmod +x test.sh $ ./test.sh
输出样例
0 1 2 3 4 5 6 7 8 9 10
- next命令
next 命令 ,它告诉 awk 跳过你所提供的所有剩下的模式和表达式,直接处理下一个输入行。next 命令帮助你阻止运行命令执行过程中多余的步骤。
要明白它是如何工作的, 让我们来分析一下 food_list.txt 它看起来像这样:
Food List Items
No | Item_Name | Price | Quantity :—:| 1|Mangoes | $3.45 | 5 2 | Apples | $2.45 | 25 3 | Pineapples | $4.45 | 55 4 | Tomatoes| $3.45 | 25 5 | Onions | $1.45 | 15 6 | Bananas | $3.45 | 30 >| 运行下面的命令,它将在每个食物数量小于或者等于 20 的行后面标一个星号:
# awk '$4 <= 20 { printf "%s/t%s/n", $0,"*" ; } $4 > 20 { print $0 ;} ' food_list.txt
No | Item_Name |Price| Quantity :—:| 1 | Mangoes| $3.45 | 5 * 2 | Apples | $2.45 | 25 3 | Pineapples | $4.45 | 55 4 | Tomatoes | $3.45 | 25 5 | Onions | $1.45 | 15 * 6 | Bananas | $3.45 | 30 上面的命令实际运行如下:
- 它用$4 <= 20表达式检查每个输入行的第四列(数量(Quantity))是否小于或者等于 20,如果满足条件,它将在末尾打一个星号 (*)。
- 它用$4 > 20表达式检查每个输入行的第四列是否大于20,如果满足条件,显示出来。
但是这里有一个问题, 当第一个表达式用{ printf “%s/t%s/n”, $0,”**” ; }命令进行标注的时候在同样的步骤第二个表达式也进行了判断这样就浪费了时间。因此当我们已经用第一个表达式打印标志行的时候就不再需要用第二个表达式$4 > 20再次打印。
要处理这个问题, 我们需要用到next 命令:
# awk '$4 <= 20 { printf "%s/t%s/n", $0,"*" ; next; } $4 > 20 { print $0 ;} ' food_list.txt
当输入行用$4 <= 20 { printf “%s/t%s/n”, $0,”*” ; next ; }命令打印以后,next命令将跳过第二个$4 > 20 { print $0 ;}表达式,继续判断下一个输入行,而不是浪费时间继续判断一下是不是当前输入行还大于 20。
next命令在编写高效的命令脚本时候是非常重要的,它可以提高脚本速度。