目录
78. 引用数组元素
79.使用循环遍历 awk 数组
80. 删除数组元素
81. 多维数组
82. SUBSEP 下标分隔符
83. 用 asort 为数组排序
84. 用 asorti 为索引排序
 相比较与其他编程语言中的传统数组, awk  的数组更为强大。  
 
 Awk  的数组,都是关联数组,即一个数组包含多个 ” 索引 / 值 ” 的元素。索引没必要是一系列  
 
 连续的数字,实际上,它可以使字符串或者数字,并且不需要指定数组长度。 
 
 语法:  
 
 arrayname[string]=value  
 
 arrayname  是数组名称  
 
 string  是数组索引  
 
 value  是为数组元素赋的值  
 
 访问  awk  数组的元素  
 
 如果要访问数组中的某个特定元素,使用  arrayname[index]  即可返回该索引中的值。  
 
 一个简单的数组赋值示例 :  
 
 $ cat array-assign.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 item["101"];  
 
 print item[102];  
 
 print item["103"];  
 
 print item[104];  
 
 print item["105"];  
 
 print item[1001];  
 
 print item["na"];  
 
 }  
 
 $ awk -f array-assign.awk  
 
 HD Camcorder  
 
 Refrigerator  
 
 MP3 Player  
 
 Tennis Racket  
 
 Laser Printer  
 
 Tennis Ball  
 
 Not Available  
 
 请注意 :  
 
 数组索引没有顺序,甚至没有从  0  或  1  开始,而是直接从  101….105  开始 , 然后直接  
 
 跳到  1001 ,又降到  55 ,还有一个字符串索引 ”na”.  
 
 数组索引可以是字符串,数组的最后一个元素就是字符串索引,即 ”na”  
 
 Awk  中在使用数组前,不需要初始化甚至定义数组,也不需要指定数组的长度。  
 
 Awk  数组的命名规范和  awk  变量命名规范相同。 以  awk  的角度来说,数组的索引通常是字符串,即是你使用数组作为索引, awk  也会当  
 
 做字符串来处理。下面的写法是等价的:  
 
 Item[101]=”HD Camcorder”  
 
 Item[“101”]=”HD Camcorder”  
 
78. 引用数组元素
 如下所示,可以使用  print  命令直接打印数组的元素,也可以把元素的值赋给其他变量以便  
 
 后续使用。  
 
 print item[101]  
 
 x=item[105]  
 
 如果视图访问一个不存在的数组元素, awk  会自动以访问时指定的索引建立该元素,并赋予  
 
 null  值。为了避免这种情况,在使用前最后检测元素是否存在。  
 
 
 使用 if 语句可以检测元素是否存在,如果返回 true,说明改元素存在于数组中。  
 
 if ( index in array-name )  
 
 一个简单的引用数组元素的例子 :  
 
 $ cat array-refer.awk  
 
 BEGIN {  
 
 x = item[55];  
 
 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 )  
 
 print "Array index 1010 contains",item[1010];  
 
 }  
 
 $ awk -f array-refer.awk  
 
 Array index 55 contains  
 
 Array index 101 contains HD Camcorder  
 
 该例中:  
 
 z  Item[55]  在引用前没有赋任何值,所以在引用是  awk  自动创建该元素并赋  null  值  
 
 z  Item[101] 是一个已赋值的缘分,所以在检查索引值时返回  true ,打印该元素  
 
 z  Item[1010] 不存在,因此检查索引值时,返回  false ,不会被打印  
 
79.使用循环遍历 awk 数组
 如果要访问数组中的所有元素,可以使用  for  的一个特殊用法来遍历数组的所有索引: 语法:  
 
 for ( var in arrayname )  
 
 actions  
 
 其中 :  
 
 var  是变量名称  
 
 in  是关键字  
 
 arrayname  是数组名  
 
 actions  是一系列要执行的  awk  语句,如果有多条语句,必须包含在 { } 中。通过把  
 
 索引值赋给变量  var ,循环体可以把所有语句应用到数组中所有的元素上。  
 
 在示例 ”for (x in item)” 中, x  是变量名,用来存放数组索引。  
 
 请注意,我们并没有指定循环执行的条件,实际上我们不比关系数组中有多少个元素,因为  
 
 awk  会自动判断,在循环结束前遍历所有元素。  
 
 下面的例子遍历数组中所有元素并打印出来。  
 
 $ cat array-for-loop.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)  
 
 print item[x]  
 
 }  
 
 $ awk -f array-for-loop.awk  
 
 Not Available  
 
 Laptop  
 
 HD Camcorder  
 
 Refrigerator  
 
 MP3 Player  
 
 Tennis Racket  
 
 Laser Printer  
 
 Tennis Ball  
 
80. 删除数组元素
 如果要删除特定的数组元素,使用  delete  语句。一旦删除了某个元素,就再也获取不到它  
 
 的值了。 
 
 语法:  
 
 delete arrayname[index];  
 
 删除数组内所有元素  
 
 for (var in array)  
 
 delete array[var]  
 
 在  GAWK  中,可以使用单个  delete  命令来删除数组的所有元素 :  
 
 Delete array  
 
 此外,下面例子中 ,item[103]=”” 并没有删除整个元素,仅仅是给它赋了  null  值。  
 
 $ cat array-delete.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";  
 
 delete item[102]  
 
 item[103]=""  
 
 delete item[104]  
 
 delete item[1001]  
 
 delete item["na"]  
 
 for(x in item)  
 
 print "Index",x,"contains",item[x]  
 
 }  
 
 $ awk -f array-delete.awk  
 
 Index no contains Not Available  
 
 Index 55 contains Laptop  
 
 Index 101 contains HD Camcorder  
 
 Index 103 contains  
 
 Index 105 contains Laser Printer  
 
81. 多维数组
 虽然  awk  只支持一维数组,但其奇妙之处在于,可以使用一维数组来模拟多维数组。  
 
 假定要创建下面的  2X2  维数组 :  
 
 10 20  
 
 30 40 其中位于 ”1,1” 的元素是  10 ,位于 ”1,2” 的元素是  20 ,等等 …, 下面把  10  赋值给 ”1,1” 的元素 :  
 
 item[“1,1”]=10  
 
 即使使用了 ”1,1” 作为索引值,它也不是两个索引,仍然是单个字符串索引,值为 ”1,1” 。所  
 
 以上面的写法中,实际上是把  10  赋给一维数组中索引 ”1,1” 代表的值。  
 
 $ 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]  
 
 }  
 
 $ awk -f array-multi.awk  
 
 30  
 
 20  
 
 40  
 
 10  
 
 现在把索引外面的引号去掉,会发生什么情况?即  item[1,1]( 而不是  item[“1,1”]):  
 
 $ 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]  
 
 }  
 
 $ awk -f array-multi2.awk  
 
 10  
 
 30  
 
 20  
 
 40  
 
 上面的例子仍然可以运行,但是结果有所不同。在多维数组中,如果没有把下标用引号引住,  
 
 awk  会使用 ”\034” 作为下标分隔符。  
 
 
 当指定元素  item[1,2] 时,它会被转换为  item[“1\0342”] 。 Awk  用把两个下标用 ”\034” 连接起  
 
 来并转换为字符串。 当使用 [“1,2”] 时,则不会使用 ”\034” ,它会被当做一维数组。  
 
 如下示例  
 
 $ cat array-multi3.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];  
 
 }  
 
 $ awk -f array-multi3.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”  
 
82. SUBSEP 下标分隔符
 通过变量  SUBSEP  可以把默认的下标分隔符改成任意字符,下面例子中, SUBSEP  被改成了分  
 
 号 :  
 
 $ cat array-multi4.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];  
 
 } 
 
 $ awk -f array-multi4.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  变量。  
 
 所以,使用多维数组时,最好不要给索引值加引号,如 :  
 
 $ cat array-multi5.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];  
 
 }  
 
 $ awk -f array-multi5.awk  
 
 Index 1:1 contains 10  
 
 Index 2:1 contains 30  
 
 Index 1:2 contains 20  
 
 Index 2:2 contains 40  
 
 
83. 用 asort 为数组排序
 asort  函数重新为元素值排序,并且把索引重置为从  1  到  n  的值,此处  n  代表数组元素个数。  
 
 假定一个数组有两个元素 :item[“something”]=”B - I’m big b” 和  item[“notsure”]=”A – I’m big a”  
 
 调用  asort  函数手,数组会以元素值排序,变成 :item[1]=”A – I’m big a”  和  item[2]=”B – I’m big  
 
 b”  
 
 
 下面例子中,数组索引是非连续的数字和字符串,调用  asort  后,元素值被排序,并且索引  
 
 值变成  1,2,3,4….  请注意, asort  函数会返回数组元素的个数。  
 
 $ 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;  
 
 }  
 
 $ 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 -------------  
 
 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 ,而是随机的。可以用下面  
 
 的方法,按索引值顺序打印 :  
 
 $ 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++)  
 
 print "Index",i,"contains",item[i]  
 
 }  
 
 $ 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  
 
 或许你已经注意到,一旦调用  asort  函数,数组原始的索引值就不复存在了。因此,你可能  
 
 想在不改变原有数组索引的情况下,使用新的索引值创建一个新的数组。  
 
 下面的例子中,原始数组 item 不会被修改,相反,使用排序后的新索引值创建新数组 itemnew,  
 
 即  itemnew[1],itemnew[2],itemnew[3], 等等。  
 
 total = asort(item,itemnew);  
 
 再次申明,务必牢记  asort  函数按元素值排序 , 但排序后使用从  1  开始的新索引值,原先的索  
 
 引被覆盖掉了。  
 
84. 用 asorti 为索引排序
 和以元素值排序相似,也可以取出所有索引值,排序,然后把他们保存在新数组中。  
 
 下面的例子展示了  asort  和  asorti  的不同 , 请牢记下面两点 :  
 
 asorti  函数为索引值 ( 不是元素值 ) 排序,并且把排序后的元素值当做元素值保存。  
 
 如果使用  asorti(state) 将会丢失原始元素值,即索引值变成了元素值。因此为了保  
 
 险起见,通常给  asorti  传递两个参数,即  asorti(state,statebbr). 这样一来,原始数组  
 
 state  就不会被覆盖了。 
 
 $ 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];  
  }  
  $ 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 
  资料来源于《SedandAwk101Hacks》,大家有兴趣可以买一本,也可以关注我,我更新完它。
曾经,我花费大半月将它们跑完,现在啥都忘了,还是要常用。
只为学习交流,不为获利,侵权联系立删。