数组
awk数组特性:
- awk的数组是关联数组(即key/value方式的hash数据结构),索引下标可为数值(甚至是负数、小数等),也可为字符串
- 在内部,awk数组的索引全都是字符串,即使是数值索引在使用时内部也会转换成字符串
- awk的数组元素的顺序和元素插入时的顺序很可能是不相同的
- awk数组支持数组的数组
awk访问、赋值数组元素
arr[idx]
arr[idx] = value
索引可以是整数、负数、0、小数、字符串。如果是数值索引,会按照CONVFMT变量指定的格式先转换成字符串。
例如:
[root@docker-01 ~]# awk ' > BEGIN{ > arr[1] = 11 > arr["1"] = 111 > arr["a"] = "aa" > arr[-1] = -11 > arr[4.3] = 4.33 > print arr[1] # 111 > print arr["1"] # 111 > print arr["a"] # aa > print arr[-1] # -11 > print arr[4.3] # 4.33 > } > ' 111 111 aa -11 4.33
通过索引的方式访问数组中不存在的元素时,会返回空字符串,同时会创建这个元素并将其值设置为空字符串。
[root@docker-01 ~]# awk ' > BEGIN{ > arr[-1]=3; > print length(arr); # 1 > print arr[1]; > print length(arr) # 2 > }' 1 2
awk数组长度
awk提供了length()
函数来获取数组的元素个数,它也可以用于获取字符串的字符数量。还可以获取数值转换成字符串后的字符数量。
[root@docker-01 ~]# awk 'BEGIN{arr[1]=1;arr[2]=2;print length(arr);print length("hello")}' 2 5
awk删除数组元素
delete arr[idx]
:删除数组arr[idx]
元素- 删除不存在的元素不会报错
delete arr
:删除数组所有元素
[root@docker-01 ~]# awk 'BEGIN{arr[1]=1;arr[2]=2;arr[3]=3;delete arr[2];print length(arr)}' 2
awk检测是否是数组
isarray(arr)可用于检测arr是否是数组,如果是数组则返回1,否则返回0。 typeof(arr)可返回数据类型,如果arr是数组,则其返回"array"。
[root@docker-01 ~]# awk 'BEGIN{ > arr[1]=1; > print isarray(arr); > print (typeof(arr) == "array") > }' 1 1
awk测试元素是否在数组中
不要使用下面的方式来测试元素是否在数组中:
if(arr["x"] != ""){...}
这有两个问题:
- 如果不存在arr["x"],则会立即创建该元素,并将其值设置为空字符串
- 有些元素的值本身就是空字符串
应当使用数组成员测试操作符in来测试:
# 注意,idx不要使用index,它是一个内置函数 if (idx in arr){...}
它会测试索引idx是否在数组中,如果存在则返回1,不存在则返回0。
[root@docker-01 ~]# awk ' > BEGIN{ > arr[1]=1; > arr[2]=2; > arr[3]=3; > > arr[1]=""; > delete arr[2]; > > print (1 in arr); # 1 > print (2 in arr); # 0 > }' 1 0
awk遍历数组
awk提供了一种for变体来遍历数组
for(idx in arr){print arr[idx]}
因为awk数组是关联数组,元素是不连续的,也就是说没有顺序。遍历awk数组时,顺序是不可预测的。
例如:
[root@docker-01 ~]# awk ' > BEGIN{ > arr["one"] = 1 > arr["two"] = 2 > arr["three"] = 3 > arr["four"] = 4 > arr["five"] = 5 > > for(i in arr){ > print i " -> " arr[i] > } > } > ' three -> 3 two -> 2 five -> 5 four -> 4 one -> 1
此外,不要随意使用for(i=0;i<length(arr);i++)
来遍历数组,因为awk数组是关联数组。但如果已经明确知道数组的所有元素索引都位于某个数值范围内,则可以使用该方式进行遍历。
[root@docker-01 ~]# awk ' > BEGIN{ > arr[1] = "one" > arr[2] = "two" > arr[3] = "three" > arr[4] = "four" > arr[5] = "five" > arr[10]= "ten" > > for(i=0;i<=10;i++){ > if(i in arr){ > print arr[i] > } > } > } > ' one two three four five ten
awk复杂索引的数组
在awk中,很多时候单纯的一个数组只能存放两个信息:一个索引、一个值。但在一些场景下,这样简单的存储能力在处理复杂需求的时候可能会捉襟见肘。
为了存储更多信息,方式之一是将第3份、第4份等信息全部以特殊方式存放到值中,但是这样的方式在实际使用过程中并不方便,每次都需要去分割值从而取出各部分的值。
另一种方式是将第3份、第4份等信息存放在索引中,将多份数据组成一个整体构成一个索引。
gawk中提供了将多份数据信息组合成一个整体当作一个索引的功能。默认方式为arr[x,y]
,其中x和y是要结合起来构建成一个索引的两部分数据信息。逗号称为下标分隔符,在构建索引时会根据预定义变量SUBSEP的值将多个索引组合起来。所以arr[x,y]
其实完全等价于arr[x SUBSEP y]
。
例如,如果SUBSEP设置为"@",那么arr[5,12] = 512
存储时,其真实索引为5@12
,所以要访问该元素需使用arr["5@12"]
。
SUBSEP的默认值为