linux 命令详解 十一
???6.? 數(shù)組:
????因為awk中數(shù)組的下標(biāo)可以是數(shù)字和字母,數(shù)組的下標(biāo)通常被稱為關(guān)鍵字(key)。值和關(guān)鍵字都存儲在內(nèi)部的一張針對key/value應(yīng)用hash的表格里。由于hash不是順序存儲,因此在顯示數(shù)組內(nèi)容時會發(fā)現(xiàn),它們并不是按照你預(yù)料的順序顯示出來的。數(shù)組和變量一樣,都是在使用時自動創(chuàng)建的,awk也同樣會自動判斷其存儲的是數(shù)字還是字符串。一般而言,awk中的數(shù)組用來從記錄中收集信息,可以用于計算總和、統(tǒng)計單詞以及跟蹤模板被匹配的次數(shù)等等。
?? ?/> cat employees
?? ?Tom Jones?????? 4424??? 5/12/66???????? 543354
?? ?Mary Adams????? 5346??? 11/4/63???????? 28765
?? ?Sally Chang???? 1654??? 7/22/54???????? 650000
?? ?Billy Black???? 1683??? 9/23/44???????? 336500
?? ?/> awk '{name[x++] = $2}; END{for (i = 0; i < NR; i++) print i, name[i]}' employees?? ?
?? ?0 Jones
?? ?1 Adams
?? ?2 Chang
?? ?3 Black
?? ?在上例中,數(shù)組name的下標(biāo)是變量x。awk初始化該變量的值為0,在每次使用后自增1,讀取文件中的第二個域的值被依次賦值給name數(shù)組的各個元素。在END模塊中,for循環(huán)遍歷數(shù)組的值。因為下標(biāo)是關(guān)鍵字,所以它不一定從0開始,可以從任何值開始。
?? ?#這里是用內(nèi)置變量NR作為數(shù)組的下標(biāo)了。
?? ?/> awk '{id[NR] = $3}; END {for (x = 1; x <= NR; x++) print id[x]}' employees
?? ?4424
?? ?5346
?? ?1654
?? ?1683
?? ?awk中還提供了一種special for的循環(huán),見如下聲明:
?? ?for (item in arrayname) {
?? ??? ?print arrayname[item]
?? ?}
?? ?/> cat db
?? ?Tom Jones
?? ?Mary Adams
?? ?Sally Chang
?? ?Billy Black
?? ?Tom Savage
?? ?Tom Chung
?? ?Reggie Steel
?? ?Tommy Tucker
?? ?/> awk '/^Tom/{name[NR]=$1}; END {for(i = 1;i <= NR; i++) print name[i]}' db
?? ?Tom
? ? ?Tom
?? ?Tom
? ? ?Tommy
?? ?從輸出結(jié)果可以看出,只有匹配正則表達(dá)式的記錄的第一個域被賦值給數(shù)組name的指定下標(biāo)元素。因為用NR作為下標(biāo),所以數(shù)組的下標(biāo)不可能是連續(xù)的,因此在END模塊中用傳統(tǒng)的for循環(huán)打印時,不存在的元素就打印空字符串了。下面我們看看用special for的方式會有什么樣的輸出。
?? ?/> awk '/^Tom/{name[NR]=$1};END{for(i in name) print name[i]}' db
?? ?Tom
?? ?Tom
?? ?Tommy
?? ?Tom
?? ?下面我們看一下用字符串作為下標(biāo)的例子:(如果下標(biāo)是字符串文字常量,則需要用雙引號括起來)?? ?
?? ?/> cat testfile2
?? ?tom
?? ?mary
?? ?sean
?? ?tom
?? ?mary
?? ?mary
?? ?bob
?? ?mary
?? ?alex
? ? /> awk '/tom/{count["tom"]++}; /mary/{count["mary"]++}; END{print "There are " count["tom"] \
?? ??? ?" Toms and " count["mary"] " Marys in the file."} testfile2
?? ?There are 2 Toms and 4 Marys in the file.
?? ?在上例中,count數(shù)組有兩個元素,下標(biāo)分別為tom和mary,每一個元素的初始值都是0,沒有tom被匹配的時候,count["tom"]就會加一,count["mary"]在匹配mary的時候也同樣如此。END模塊中打印出存儲在數(shù)組中的各個元素。
?? ?/> awk '{count[$1]++}; END{for(name in count) printf "%-5s%d\n",name, count[name]}' testfile2
?? ?mary 4
?? ?tom? 2
?? ?alex 1
?? ?bob? 1
?? ?sean 1
?? ?在上例中,awk是以記錄的域作為數(shù)組count的下標(biāo)。
?? ?/> awk '{count[$1]++; if (count[$1] > 1) name[$1]++}; END{print "The duplicates were "; for(i in name) print i}' testfile2
?? ?The duplicates were
?? ?mary
?? ?tom
?? ?在上例中,如count[$1]的元素值大于1的時候,也就是當(dāng)名字出現(xiàn)多次的時候,一個新的數(shù)組name將被初始化,最后打印出那么數(shù)組中重復(fù)出現(xiàn)的名字下標(biāo)。
?? ?之前我們介紹的都是如何給數(shù)組添加新的元素,并賦予初值,現(xiàn)在我們需要介紹一下如何刪除數(shù)組中已經(jīng)存在的元素。要完成這一功能我們需要使用內(nèi)置函數(shù)delete,見如下命令:
?? ?/> awk '{count[$1]++}; \
?? ??? ?END{for(name in count) {\
?? ???????????? if (count[name] == 1)\
?? ???????????????? delete count[name];\
?? ???????? } \
?? ???????? for (name in count) \
?? ???????????? print name}' testfile2
?? ?mary
?? ?tom
?? ?上例中的主要技巧來自END模塊,先是變量count數(shù)組,如果數(shù)組中某個元素的值等于1,則刪除該元素,這樣等同于刪除只出現(xiàn)一次的名字。最后用special for循環(huán)打印出數(shù)組中仍然存在的元素下標(biāo)名稱。
?? ?最后我們來看一下如何使用命令行參數(shù)數(shù)組,見如下命令:
?? ?/> awk 'BEGIN {for(i = 0; i < ARGC; i++) printf("argv[%d] is %s.\n",i,ARGV[i]); printf("The number of arguments, ARGC=%d\n",ARGC)}' testfile "Peter Pan" 12
?? ?argv[0] is awk.
?? ?argv[1] is testfile.
?? ?argv[2] is Peter Pan.
?? ?argv[3] is 12.
?? ?The number of arguments, ARGC=4
?? ?從輸出結(jié)果可以看出,命令行參數(shù)數(shù)組ARGV是以0作為起始下標(biāo)的,命令行的第一個參數(shù)為命令本身(awk),這個使用方式和C語句main函數(shù)完全一致。
?? ?/> awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"?? ?
?? ?ARGV[2] is bob
?? ?bob
?? ?awk: (FILENAME=testfile2 FNR=9) fatal: cannot open file `bob' for reading (No such file or directory)
?? ?先解釋一下以上命令的含義,name變量被賦值為命令行的第三個參數(shù),即bob,之后再在輸入文件中找到匹配該變量值的記錄,并打印出該記錄。
?? ?在輸出的第二行報出了awk的處理錯誤信息,這主要是因為awk將bob視為輸入文件來處理了,然而事實上這個文件并不存在,下面我們需要做進(jìn)一步的處理來修正這個問題。
?? ?/> awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]; delete ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"?? ?
?? ?ARGV[2] is bob
?? ?bob
?? ?從輸出結(jié)果中我們可以看到我們得到了我們想要的結(jié)果。需要注意的是delete函數(shù)的調(diào)用必要要在BEGIN模塊中完成,因為這時awk還沒有開始讀取命令行參數(shù)中指定的文件。
轉(zhuǎn)載于:https://blog.51cto.com/andra/814833
總結(jié)
以上是生活随笔為你收集整理的linux 命令详解 十一的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 使用反射设置某个对象的属性或读取某
- 下一篇: Linux下Nginx+PHP+MySQ