文章目录
前言
awk的循环有很多种循环结构,其中最常见的是for循环。
一、AWK for循环的两种基本语法
1. 计数器控制for循环用法
- 计数器控制的for循环通常用于重复操作特定次数或在某个范围内。
for (初始化; 条件; 迭代) { # 循环体 } 初始化:初始化一个计数器或变量,通常在循环开始之前执行。 条件:在每次迭代之前检查的条件,如果条件为真,循环会继续执行;如果条件为假,循环会终止。 迭代:在每次迭代之后执行的操作,通常用于递增或递减计数器。 例如打印数字0到10 awk 'BEGIN { for (i=0; i<=10; i++) { print i } }' 例如计算1到100的和 awk 'BEGIN { sum=0 for (i=1; i<=100; i++) { sum += i } print sum }' 用数学公式(1+n)*n/2,这可以让时间复杂度变成O(1)。 awk 'BEGIN{print (1+100)*100/2}'
2. 遍历数组元素的for循环
- 使用遍历数组元素的for循环,这个先说一个简单的例子,然后详细说下awk中数组的操作
遍历数组元素的for循环:for (变量 in 数组) { # 循环体 } 变量:用于遍历数组元素的变量。 数组:包含要遍历的元素的数组。 我们先定义一个数组,awk的数组默认是关联数组 例如像Go里的map数据结构一样。 awk 'BEGIN { #awk加注释,跟shell一样,#号开头就可以了。 #我们定义一个names的数组,键存的是名字, 值是年龄。 names["Alice"] = 25 names["Bob"] = 30 names["Carol"] = 28 #我们可以循环遍历names数组,并打印元素 for (name in names) { printf("%s的年龄是%d岁\n", name, names[name]) } }'
二、AWK中数组的基本操作
1. awk数组的声明和初始化
- 它们是有序的、可索引的数据集合,可以容纳各种数据类型,包括字符串和数字。
awk数组的索引可以是数字或字符串。
在awk中,数组可以通过以下语法声明和初始化:
这里,array 是数组的名称,index 是数组元素的索引,可以是数字或字符串,value 是要存储在数组元素中的值。例如:array[index] = value
在上面的示例中,我们创建了一个名为myArray的数组,并使用不同的索引存储了字符串和数字。myArray["apple"] = 5 myArray["banana"] = 8 myArray[3] = "cherry"
2. 获取数组元素
- 要访问数组元素,只需使用数组名称和索引。例如,要获取myArray中"apple"的值,可以这样做:
value = myArray["apple"] 例子 awk 'BEGIN { myArray["apple"] = 5 myArray["banana"] = 8 myArray[3] = "cherry" print myArray["apple"] }' 输出: 5
- 同样,要获取myArray中索引为3的值,可以使用:
value = myArray[3] 例子 awk 'BEGIN { myArray["apple"] = 5 myArray["banana"] = 8 myArray[3] = "cherry" print myArray[3] }' 输出: cherry
3. 遍历数组
-
Awk提供了多种方法来遍历数组的元素。最常见的方法是使用for循环:
for (数组下标变量 in 数组) { # 在这里处理数组元素 print 数组下标变量, 数组[数组下标变量] } 实例1. awk 'BEGIN { myArray["apple"] = 5 myArray["banana"] = 8 myArray["cherry"] = 18 for (i in myArray) { printf("名字: %s, 年龄: %d\n", i, myArray[i]) } }' 输出: 名字: apple, 年龄: 5 名字: banana, 年龄: 8 名字: cherry, 年龄: 18 实例2. 如果数组下标是数字递增的话,我们还可以用这种方式遍历数组 BEGIN { #创建下标为int数字的数组 my[0]="dad" my[1]="dsd" my[2]="dsjadh" #length() 函数可以获取数组的大小 for (i=0; i<length(my); i++) { printf("数组的下标为: %d, 对应的值为: %s\n", i, my[i]) } }
-
实际操作awk数组实例练习
例如我们有一个下面这样的文本。
This is a test. This is only a test. If this were a real test, you would be notified.
这是一个包含一些重复单词的简短文本,可以用来测试你的awk程序。当你运行你的awk程序,它应该能够识别并统计出现的单词以及它们的出现次数,然后生成相应的输出。
使用上述示例文本数据,你的awk程序应该能够生成类似下面的表格:单词 出现次数 you 1 were 1 only 1 this 1 be 1 real 1 If 1 a 3 This 2 notified 1 would 1 test 3 is 2 我们可以这样写
[root@wangfei awk]# str="This is a test. This is only a test. If this were a real test, you would be notified." [root@wangfei awk]# echo "$str" | awk '{ for (i = 1; i <= NF; i++) { word = $i gsub("[^a-zA-Z]", "", word) # 移除非字母字符 if (word != "") { word_count[word]++ } } } END { print "| 单词 | 出现次数 |" print "|------|----------|" for (word in word_count) { printf("| %s | %d |\n", word, word_count[word]) } }' 输出结果: | 单词 | 出现次数 | |------|----------| | you | 1 | | were | 1 | | only | 1 | | this | 1 | | be | 1 | | real | 1 | | If | 1 | | a | 3 | | This | 2 | | notified | 1 | | would | 1 | | test | 3 | | is | 2 |
-
详细解释每一部分的目的和功能:
1. 遍历单词
for (i = 1; i <= NF; i++) { word = $i # 在这里处理每个单词 }
这部分的目的是遍历每一行中的单词。NF是内置变量,代表每一行中的字段数。$i表示第 i 个字段(在这里,字段是由空格分隔的单词)。我们将每个单词存储在 word 变量中以进行进一步处理。
2.移除非字母字符gsub("[^a-zA-Z]", "", word) word_count[word]++
在这一步中,我们使用gsub函数删除了 word 变量中的非字母字符。这是为了确保我们只统计纯单词,而不包括标点符号或其他非字母字符。
gsub:是Awk的内置函数,用于全局替换字符串。
[^a-zA-Z]:是一个正则表达式,它匹配除小写字母a-z和大写字母A-Z之外的所有字符。
“”:是替换的内容,这里我们将匹配到的字符替换为空字符串,从而删除它们。3. 统计单词出现次数
word_count[word]++
我们使用Awk数组来统计每个单词的出现次数。word_count 是一个数组,以word 变量的内容作为键,增加其对应的值来统计单词出现的次数。如果这是第一次遇到这个单词,它的值将被初始化为0,然后增加1。
4. 创建输出表格END { print "| 单词 | 出现次数 |" print "|------|----------|" for (word in word_count) { printf("| %s | %d |\n", word, word_count[word]) } }'
在awk程序的结尾部分,我们使用END块来创建表格。首先,我们输出表格的头部,然后使用一个 for 循环遍历 word_count 数组中的每个单词,并打印它们的单词和出现次数。这将创建一个表格,显示每个单词和它们的出现次数。
总结
这次学了数组和for循环的基本操作,下章讲awk中数组的常用技巧和高级操作