from:http://techbbs.zol.com.cn/1/60_305.html
数组是一个包含一系列元素的表。数组的元素通过下标区分。下标可以是数字也可以是字符串。这个主节点描述了在awk 中数组如何工作、如何使用数组的元素、如何遍历数组每个元素、如何移除某个元素等内容。同时,描述了 awk 如何模拟多维数组和一些不常见的数组应用。并且,这个节点讲述了 gawk 如何根据数据的下标对数据进行排序。
Awk 在同一个命名空间里维护变量、数组和函数的名字,因此在一个 awk 程序里不允许变量和数组重名。
1 数组介绍
Awk 语言支持一维数组用于存放一组相关的字符串或者数字。每一个数组必需有一个名字。数组的命名与变量的命名遵守相同的惯例和约束。
Awk 的数组和其他编程语言的数组概念看上去类似。但是确有基本的不同。主要有两点
1、 awk 中的数组在使用一个数组之前不需要制定数组的大小( size )。
2、 任何数字或者字符串都可以作为数组的下标,而不仅仅是连续的整数。
在大部分的编程语言中,数组必需先定义,包括包含多少个元素(也就是数组的大小),然后才能使用。在这些语言中,数组的定义将使系统分配连续的内存 块给数组的元素。通常,这些数组的下标必需是正整数。例如,下标 0 指向数组的第一个元素,存在内存块的最前端。下标 1 指向数组的第二个元素,在内存块中紧挨第一个元素之后保存。不可以添加元素到数组,因为数组在定义的时候已经指定了空间的大小。(一些语言允许用户任意指定下标的起始值和结束值,例如15..27 ,但是数组的大小还是固定的)。
一个具有四个元素的连续数组通常如下:
值 |
8 |
foo |
“” |
30 |
下标 |
0 |
1 |
2 |
3 |
在 awk 中,数组是关联数组,它的特点是:
1、 数组的下标可以是整数,也可以是负数甚至是字符串
2、 数组的下标可以不连续。
Awk 的变量 IGNORECASE 的值不影响数组下标。
当 awk 创建一个数组的时候,如果没有指定下标,默认已连续整数作为下标,起始值是 1.
Awk 的数组是什么高效的,访问一个元素的时间跟元素的数量无关。
注: awk 的下标其实都是字符串,如我们输入的是数字 1 , awk 会自动的转换为字符串“ 1 ”。
2 引用元素
引用 awk 元素的基本方法是:
ARRAY[INDEX] |
注: 在此引用方式中除非 [ ] 中写的是变量,否则需要添加双引号,即字符串必需添加双引号的规则在数组的下标中也必需遵守,但如果下标是全数字,则可以不加引号,例:
Bb=”123” arr[bb] awk 将 bb 认作变量,获取的是 arr[“123”] 的值 arr[234] awk 将 234 认作字符串,虽然 234 没加引号。因为变量的定义不能用全数字,所以 234 肯定是字符串,而不是变量。 arr[“ bb” ] awk 将 bb 认作字符串,获取的是 arr[“bb”] 的值 |
有时候,数组的 value 会为空。 value 为空的元素包含两种情况, 1 、本身 value 为空。 2 、通过 delete 删除后的元素。这两种情况都可以被正常引用。但不幸的是,如果引用了一个不存在的元素,会导致 awk 创建这个元素, value 为空,这样,会导致 awk 的内存浪费。
如果要查询具有某个 index 值的元素是否存在可以用如下的表达式:
INDEX in ARRAY |
这个表达式仅仅测试具有 INDEX 的元素在 ARRAY 中是否存在。如果不存在,该表达式不会导致产生以 INDEX 为下标的 value 为空的元素。
如果元素存在,该表达式返回值 1 ( true )
反之,返回 0 ( false )
例:测试在数组 frequencies 中是否存在下标为 2 的元素
. if (2 in frequencies) print “Sub 2 is present.”
|
注: 不能测试 frequencies 中是否存在 value 为 2 的元素,除非 scan 数组中的所有元素。
3 给元素赋值
给 awk 的数组赋值,只能采用如下形式:
ARRAY[SUB] = VALUE |
ARRAY :数组名字
SUB :下标
VALUE :值
4 数组实例
以下文件以数字为行首
5 I am the Five man 2 Who are you? The new number two! 4 . . . And four on the floor 1 Who is number one? 3 I three you. |
以下的 awk 程序将以上文件,按行首的数字顺序逐行打印:
{ if ($1 > max) max = $1 arr[$1] = $0 } END { for (x = 1; x <= max; x++) print arr[x] } |
程序第一部分实现两个功能:
1、 得到行首数字的最大值
2、 已行首数字为下标,将相应的行存入数组
程序执行完毕输出结果如下:
1 Who is number one? 2 Who are you? The new number two! 3 I three you. 4 . . . And four on the floor 5 I am the Five man |
如果行首数字有相重的情况,后面的行将覆盖前面的行,前面的行不会打印出来。
如果有行首数字为空的情况,可以用以下的增强方式予以处理:
END { for (x = 1; x <= max; x++) if (x in arr) print arr[x] } |
注: awk 可以生成下标为空的元素,但是引用方式必需是 arr[ “” ], 而不是 arr[]
5 遍历数组
在使用数组的程序里,经常会使用一个循环让数组里的每一个元素都执行一次某一个操作。在其他程序里,数组的下标是连续的正整数,因此所有的下标很容易通过从低到高实现遍历。但这个方法在 awk 里不能使用,因为 awk 的下标可以是数字也可以是字符串。因此, awk 使用一种特别的语句来遍历数组里的元素:
for (VAR in ARRAY) BODY |
以上的循环将实现让数组 ARRAY 里的每一个元素都执行一次 BODY 。
以下程序的第一部分,将输入文本的每一个单词都作为下标存放入数组,如单词有重复,仅仅保留一个,因数组的下标是不能重复的。
程序的第二部分,将这些单词判断是否大于 10 个字母。如是,打印出来,并将计数器 +1 。最后打印出输入文件中有多少个单词超过 10 个字母。
#!/bin/awk { for (i = 1; i <= NF; i++) used[$i] = 1 } END { for (x in used) if (length(x) > 10) { ++num_long_words print x } print num_long_words, “words longer than 10 characters” } |
注: 1 、下标的输出顺序是 awk 使用内置规则排列的,不要试图在 for 循环内试图改变、控制这个顺序,否则会出现意料不到的后果。
2 、同样,在 for 循环内不要更改 VAR 的值,在上例就是在黄色区域内,不要更改 x 的值,否则,同样会出现意料不到的后果。
6 删除元素
删除单个元素
delete ARRAY[INDEX] |
删除整个数组方法 1
for (VAR in ARRAY) delete ARRAY[VAR] |
删除整个数组方法 2 (该方法 gawk 专用,可移植性差,但效率是方法 1 的 3 倍左右)
delete ARRAY |
删除整个数组方法 3( 该方法具移植性,但其实是一种变通的方法,就如同医药里的偏方。 Split 试图分割一个 null string ,发现没有可分割和输出的,于是它简单的 clear 了数组 ARRAY)
split(””, ARRAY) |
一个元素被删除和给他赋空值是不同的,所以以下两端代码结果也截然不同:
delete foo[4] if (4 in foo) print “This will never be printed” |
结果:不会打印“ This will never be printed ”
foo[4] = “” if (4 in foo) print “This is printed, even though foo[4] is empty” |
结果:会打印“ This is printed, even though foo[4] is empty ”
Awk 的数组和变量用的是同一个地址空间,数组的名字和变量不能重名。即使数组删除了也不能将名字用于变量命名,以下命令会报错:
a[1] = 3; delete a; a = 3 |
7 数字下标
Awk 的数组下标都是字符串,如果输入的是数字, awk 会自动转换。 Awk 下标中的数字,受变量 CONVFMT 的影响。例:
xyz = 12.153
data[xyz] = 1
8.数组赋值
单个赋值: Tarray[1]=“cheng mo” Tarray[2]=“800927”
多个赋值:awk ‘BEGIN{info=”it is a test”;lens=split(info,tA,” “);print length(tA),lens,tA[1];}’
4 4 it #awk的数组下标从1开始的。
bash的多个赋值:a=(1 2 4) ;echo ${a[2]}
今天的文章awk数组简介分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12229.html