linux 关联数组,Linux高级文本处理之gawk关联数组

Awk 的数组,都是关联数组,即一个数组包含多个”索引/值”的元素。 索引没必要是一系列 连续的数字,实际上,它可以使字符串或者数字,并且不需要指定数组长度。

语法:

arrayname[string]=value

arrayname 是数组名称

string 是数组索引

value 是为数组元素赋的值

访问 awk 数组的元素

如果要访问数组中的某个特定元素,使用 arrayname[index] 即可返回该索引中的值。

实例1:

[root@localhost ~]# awk '

>BEGIN{ item[101]="HD Camcorder";

>item["102"]="Refrigerator";

>item[103]="MP3 Player";

>item["na"]="Young"

>print item[101];

>print item["102"];    #注意带引号不带引号awk都视为字符串来处理

>print item[103];

>print item["na"];}'   #字符串索引需要加双引号

HD Camcorder

Refrigerator

MP3 Player

Young

注意:

数组索引没有顺序,甚至没有从 0 或 1 开始.

数组索引可以是字符串,数组的最后一个元素就是字符串索引,即”na”

Awk 中在使用数组前,不需要初始化甚至定义数组,也不需要指定数组的长度。

Awk 数组的命名规范和 awk 变量命名规范相同。

以 awk 的角度来说,数组的索引通常是字符串,即是你使用数组作为索引, awk 也会当 做字符串来处理。下面的写法是等价的:

Item[101]="HD Camcorder"

Item["101"]="HD Camcorder"

一、引用数组元素

如果试图访问一个不存在的数组元素, awk 会自动以访问时指定的索引建立该元素,并赋予 null 值。 为了避免这种情况,在使用前最后检测元素是否存在。

使用 if 语句可以检测元素是否存在,如果返回 true,说明改元素存在于数组中。

if ( index in array-name )

实例2:一个简单的引用数组元素的例子

[root@localhost ~]# cat arr.awk

BEGIN {

x = item[55];  #在引用前没有赋任何值,所以在引用是 awk 自动创建该元素并赋 null 值

if ( 55 in item )

print "Array index 55 contains",item[55];

item[101]="HD Camcorder";

if ( 101 in item )

print "Array index 101 contains",item[101];

if ( 1010 in item )  #不存在,因此检查索引值时,返回 false,不会被打印

print "Array index 1010 contains",item[1010];

}

[root@localhost ~]# awk -f arr.awk

Array index 55 contains

Array index 101 contains HD Camcorder

二、使用循环遍历 awk 数组

如果要访问数组中的所有元素, 可以使用 for 的一个特殊用法来遍历数组的所有索引:

语法:

for ( var in arrayname )

actions

说明:

var 是变量名称

in 是关键字

arrayname 是数组名

actions 是一系列要执行的 awk 语句,如果有多条语句,必须包含在{ }中。 通过把索引值赋给变量 var,循环体可以把所有语句应用到数组中所有的元素上。

实例1:将数组中元素全部打印出来

[root@localhost ~]# cat arr-for.awk

BEGIN {

item[101]="HD Camcorder";

item[102]="Refrigerator";

item[103]="MP3 Player";

item[104]="Tennis Racket";

item[105]="Laser Printer";

item[1001]="Tennis Ball";

item[55]="Laptop";

item["no"]="Not Available";

for(x in item)  #x 是变量名,用来存放数组索引,无需制定条件,awk自行判断

print item[x];

}

[root@localhost ~]# awk -f arr-for.awk

Not Available

Laptop

HD Camcorder

Refrigerator

MP3 Player

Tennis Racket

Laser Printer

Tennis Ball

三、删除数组元素

如果要删除特定的数组元素,使用 delete 语句。一旦删除了某个元素,就再也获取不到它 的值了。

语法:

delete arrayname[index];

删除数组内所有元素:

for (var in array)

delete array[var]

在 GAWK 中,可以使用单个 delete 命令来删除数组的所有元素:

Delete array

实例1:

[root@localhost ~]# awk '

>BEGIN{item[101]="HD Camcorder";

>item[102]="Refrigerator";

>item[103]="MP3 Player";

>delete item[101];

>print item[101];print item[102];

>for(x in item) delete item[x]; #使用for循环删除全部数组

>print item[102];print item[103];}'

Refrigerator

[root@localhost ~]#

实例2���

[root@localhost ~]# awk '

>BEGIN{item[1]="a";

>item[2]="b";item[3]="c";

>delete item;   #使用delete直接加数组名称删除全部数组

>for(x in item) print item[x];}'

四、多维数组

虽然 awk 只支持一维数组,但可以使用一维数组来模拟多维数组。

实例1:

[root@localhost ~]# cat array-multi.awk

BEGIN {

item["1,1"]=10;

item["1,2"]=20;

item["2,1"]=30;

item["2,2"]=40

for (x in item)

print item[x]

}

[root@localhost ~]# awk -f array-multi.awk

30

20

40

10

说明:即使使用了”1,1”作为索引值,它也不是两个索引,仍然是单个字符串索引,值为”1,1”。所 以item[“1,1”]=10,实际上是把 10 赋给一维数组中索引”1,1”代表的值。

实例2:将双引号去掉

[root@localhost ~]# cat array-multi2.awk

BEGIN {

item[1,1]=10;

item[1,2]=20;

item[2,1]=30;

item[2,2]=40

for (x in item)

print item[x]

}

[root@localhost ~]# awk -f array-multi2.awk

10

30

20

40

说明:上面的例子仍然可以运行,但是结果有所不同。在多维数组中,如果没有把下标用引号引住, awk 会使用”\034”作为下标分隔符。

当指定元素 item[1,2]时,它会被转换为 item[“1\0342”]。 Awk 用把两个下标用”\034”连接起 来并转换为字符串。

实例3:

[root@localhost ~]# cat 034.awk

BEGIN {

item["1,1"]=10;

item["1,2"]=20;

item[2,1]=30;

item[2,2]=40;

for(x in item)

print "Index",x,"contains",item[x];

}

[root@localhost ~]# awk -f 034.awk

Index 1,2 contains 20

Index 21 contains 30

Index 22 contains 40

Index 1,1 contains 10

说明:

索引”1,1”和”1,2”放在了引号中,所以被当做一维数组索引, awk 没有使用下标分 隔符,因此,索引值被原封不动地输出。

所以 2,1 和 2,2 没有放在引号中,所以被当做多维数组索引, awk 使用下标分隔符 来处理,因此索引变成”2\0341”和”2\0342”,于是在两个下标直接输出了非打印字符 “\034”

五、SUBSEP 下标分隔符

通过变量 SUBSEP 可以把默认的下标分隔符改成任意字符。

实例1:

[root@localhost ~]# cat subsep.awk

BEGIN {

SUBSEP=":";

item["1,1"]=10;

item["1,2"]=20;

item[2,1]=30;

item[2,2]=40;

for(x in item)

print "Index",x,"contains",item[x];

}

[root@localhost ~]# awk -f subsep.awk

Index 1,2 contains 20

Index 2:1 contains 30

Index 2:2 contains 40

Index 1,1 contains 10

说明:索引”1,1”和”1,2”由于放在了引号中而没有使用 SUBSEP 变量。

注意:使用多维数组时,最好不要给索引值加引号,直接使用SUBSEP变量制定索引分隔符。

六、用 asort 为数组排序

asort 函数重新为元素值排序,并且把索引重置为从 1 到 n 的值,此处 n 代表数组元素个数。

实例1:

[root@localhost ~]# cat asort.awk

BEGIN {

item[101]="HD Camcorder";

item[102]="Refrigerator";item[103]="MP3 Player";

item[104]="Tennis Racket";

item[105]="Laser Printer";

item[1001]="Tennis Ball";

item[55]="Laptop";

item["na"]="Not Available";

print "---------- Before asort -------------"

for(x in item)

print "Index",x,"contains",item[x]

total = asort(item);

print "---------- After asort -------------"

for(x in item)

print "Index",x,"contains",item[x]

print "Return value from asort:",total;

}

[root@localhost ~]# awk -f asort.awk

---------- Before asort -------------

Index 55 contains Laptop

Index 101 contains HD Camcorder

Index 102 contains Refrigerator

Index 103 contains MP3 Player

Index 104 contains Tennis Racket

Index 105 contains Laser Printer

Index na contains Not Available

Index 1001 contains Tennis Ball

---------- After asort -------------  #awk数组索引是从1开始的不是0

Index 4 contains MP3 Player

Index 5 contains Not Available

Index 6 contains Refrigerator

Index 7 contains Tennis Ball

Index 8 contains Tennis Racket

Index 1 contains HD Camcorder

Index 2 contains Laptop

Index 3 contains Laser Printer

Return value from asort: 8

注意:一旦调用 asort 函数,数组原始的索引值就不复存在了,索引并不是按照1-8排序而是随机排序。

实例2:增加索引排序功能

[root@localhost ~] cat asort1.awk

BEGIN {

item[101]="HD Camcorder";

item[102]="Refrigerator";item[103]="MP3 Player";

item[104]="Tennis Racket";

item[105]="Laser Printer";

item[1001]="Tennis Ball";

item[55]="Laptop";

item["na"]="Not Available";

total = asort(item);

for(i=1;i<=total;i++)  #添加for循环控制索引输出的顺序

print "Index",i,"contains",item[i]

}

[root@localhost ~] awk -f asort1.awk

Index 1 contains HD Camcorder

Index 2 contains Laptop

Index 3 contains Laser Printer

Index 4 contains MP3 Player

Index 5 contains Not Available

Index 6 contains Refrigerator

Index 7 contains Tennis Ball

Index 8 contains Tennis Racket

七、用 asorti 为索引排序

和以元素值排序相似,也可以取出所有索引值,排序,然后把他们保存在新数组中。

说明:

asorti 函数为索引值(不是元素值)排序,并且把排序后的元素值当做元素值保存。

如果使用 asorti(state)将会丢失原始元素值,即索引值变成了元素值。因此为了保险起见,通常给 asorti 传递两个参数,即 asorti(state,statebbr).这样一来,原始数组state 就不会被覆盖了。

实例1:

[root@localhost ~]# cat asorti.awk

BEGIN {

state["TX"]="Texas";

state["PA"]="Pennsylvania";

state["NV"]="Nevada";

state["CA"]="California";

state["AL"]="Alabama";

print "-------------- Function: asort -----------------"

total = asort(state,statedesc);

for(i=1;i<=total;i++)

print "Index",i,"contains",statedesc[i];

print "-------------- Function: asorti -----------------"

total = asorti(state,stateabbr);

for(i=1;i<=total;i++)   #索引按顺序输出也需要自行排序

print "Index",i,"contains",stateabbr[i];

}

[root@localhost ~]# awk -f asorti.awk

-------------- Function: asort -----------------

Index 1 contains Alabama

Index 2 contains California

Index 3 contains Nevada

Index 4 contains Pennsylvania

Index 5 contains Texas

-------------- Function: asorti -----------------

Index 1 contains AL

Index 2 contains CA

Index 3 contains NV

Index 4 contains PA

Index 5 contains TX

补充实例:利用数组删除重复行

[root@localhost ~]# cat alpha

注解:

为何上面的命令将重复的行去掉了呢?原因如下:首先,当读入第一个字符a时,关联数组array的以a为索引的值为空,即array[a]=0,将此取反为1,逻辑上为真,则输出第一行,然后自相加为2。其次,当读入第二个值b时,同理可知为1,array也为1。当第二次读入a时,因为array[a]的值已经为2,(逻辑)取反之后为0,逻辑上是假,则不会输出,自相加最后为1。

注意:第一点,!的运算顺序比++要更优先;第二点,++是在print之后才会执行。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值