亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 24596208 | 回復: 24596208
打印 上一主題 下一主題

[學習共享] awk數(shù)組的學習心得 [復制鏈接]

論壇徽章:
2
射手座
日期:2014-10-10 15:59:4715-16賽季CBA聯(lián)賽之上海
日期:2016-03-03 10:27:14
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-04-30 08:42 |只看該作者 |倒序瀏覽
本帖最后由 yinyuemi 于 2011-06-26 00:29 編輯

在文本處理的工作中,awk的數(shù)組是必不可少的工具,在這里,同樣以總結經(jīng)驗和教訓的方式和大家分享下我的一些學習心得,如有錯誤的地方,請大家指正和補充。

awk的數(shù)組,一種關聯(lián)數(shù)組(Associative Arrays),下標可以是數(shù)字和字符串。因無需對數(shù)組名和元素提前聲明,也無需指定元素個數(shù) ,所以awk的數(shù)組使用非常靈活。
首先介紹下幾個awk數(shù)組相關的知識點:

<1>建立數(shù)組

  1. array[index] = value :數(shù)組名array,下標index以及相應的值value。
復制代碼
<2>讀取數(shù)組值

  1. { for (item in array)  print array[item]} # 輸出的順序是隨機的
  2. {for(i=1;i<=len;i++)  print array[i]} # Len 是數(shù)組的長度
復制代碼
<3>多維數(shù)組,array[index1,index2,……]:SUBSEP是數(shù)組下標分割符,默認為“\034”?梢允孪仍O定SUBSEP,也可以直接在SUBSEP的位置輸入你要用的分隔符,如:

  1. awk 'BEGIN{SUBSEP=":";array["a","b"]=1;for(i in array) print i}'
  2. a:b
  3. awk 'BEGIN{array["a"":""b"]=1;for(i in array) print i}'
  4. a:b
復制代碼
但,有些特殊情況需要避免,如:

  1. awk 'BEGIN{
  2. SUBSEP=":"
  3. array["a","b:c"]=1               # 下標為“a:b:c”
  4. array["a:b","c"]=2               #下標同樣是“a:b:c”
  5. for (i in array) print i,array[i]}'
  6. a:b:c 2                                 #所以數(shù)組元素只有一個。
復制代碼
<4>刪除數(shù)組或數(shù)組元素: 使用delete 函數(shù)

  1. delete array                     #刪除整個數(shù)組
  2. delete array[item]           # 刪除某個數(shù)組元素(item)
復制代碼
<5> 排序:awk中的asort函數(shù)可以實現(xiàn)對數(shù)組的值進行排序,不過排序之后的數(shù)組下標改為從1到數(shù)組的長度。在gawk 3.1.2以后的版本還提供了一個asorti函數(shù),這個函數(shù)不是依據(jù)關聯(lián)數(shù)組的值,而是依據(jù)關聯(lián)數(shù)組的下標排序,即asorti(array)以后,仍會用數(shù)字(1到數(shù)組長度)來作為下標,但是array的數(shù)組值變?yōu)榕判蚝蟮脑瓉淼南聵耍悄阒付硪粋參數(shù)如:asorti(a,b)。(非常感謝lionfun對asorti的指正和補充


  1. echo 'aa
  2. bb
  3. aa
  4. bb
  5. cc' |\
  6. awk '{a[$0]++}END{l=asorti(a);for(i=1;i<=l;i++)print a[i]}'
  7. aa
  8. bb
  9. cc

  10. echo 'aa
  11. bb
  12. aa
  13. bb
  14. cc' |\
  15. awk '{a[$0]++}END{l=asorti(a,b);for(i=1;i<=l;i++)print b[i],a[b[i]]}'
  16. aa 2
  17. bb 2
  18. cc 1
復制代碼


下面說awk數(shù)組的實際應用。

1.  除去重復項, 這個不多說, 只給出代碼:

  1. awk '!a[$0]++' file(s)                  
  2. awk '!($0 in a){a[$0];print}' file(s)   
復制代碼
另一種:http://www.72891.cn/thread-1859344-1-1.html

2. 計算總數(shù)(sum),如:

  1. awk  '{name[$0]+=$1};END{for(i in name) print  i, name[i]}'

  2. 再舉個例子:

  3. echo "aaa 1
  4. aaa 1
  5. ccc 1
  6. aaa 1
  7. bbb 1
  8. ccc 1" |awk '{a[$1]+=$2}END{for(i in a) print i,a[i]}'
  9. aaa 3
  10. bbb 1
  11. ccc 2


復制代碼
3. 查看文件差異。

  1. cat file1
  2. aaa
  3. bbb
  4. ccc
  5. ddd
  6. cat file2
  7. aaa
  8. eee
  9. ddd
  10. fff
復制代碼
<1>  合并file1和file2,除去重復項:

  1. awk 'NR==FNR{a[$0]=1;print}   #讀取file1,建立數(shù)組a,下標為$0,并賦值為1,然后打印
  2. NR>FNR{                   #讀取file2
  3. if(!(a[$0])) {print }      #如果file2 的$0不存在于數(shù)組a中,即不存在于file1,則打印。
  4. }' file1 file2
  5. aaa
  6. bbb
  7. ccc
  8. ddd
  9. eee
  10. fff
復制代碼
<2> 提取文件1中有,但文件2中沒有:

  1. awk 'NR==FNR{a[$0]=1}           #讀取file2,建立數(shù)組a,下標為$0,并賦值為1
  2. NR>FNR{                   #讀取file1
  3. if(!(a[$0])) {print }      #如果file1 的$0不存在于數(shù)組a中,即不存在于file2,則打印。
  4. }' file2 file1
  5. bbb
  6. ccc
復制代碼
另:http://www.72891.cn/viewthr ... &page=1#pid15547885

4.  排序:

  1. echo "a
  2. 1
  3. 0
  4. b
  5. 2
  6. 10
  7. 8
  8. 100" |
  9. awk '{a[$0]=$0} #建立數(shù)組a,下標為$0,賦值也為$0
  10. END{
  11. len=asort(a)      #利用asort函數(shù)對數(shù)組a的值排序,同時獲得數(shù)組長度len
  12. for(i=1;i<=len;i++) print i "\t"a[i]  #打印
  13. }'
  14. 1       0
  15. 2       1
  16. 3       2
  17. 4       8
  18. 5       10
  19. 6       100
  20. 7       a
  21. 8       b
復制代碼
5.  有序輸出:采用(index in array)的方式打印數(shù)組值的順序是隨機的,如果要按原序輸出,則可以使用下面的方法:http://bbs2.chinaunix.net/viewthread.php?tid=1811279

  1. awk '{a[$1]=$2
  2. c[j++]=$1}
  3. END{
  4. for(m=0;m<j;m++)print c[m],a[c[m]]
  5. }'
復制代碼
6.  多個文本編輯:這里主要指的是待處理的文本之間的格式上有區(qū)別,如分隔符不同,;或是待處理文本需提取的信息的位置不同,如不同的列或行。
<例1>:

  1. cat file1
  2. g1.1 2
  3. g2.2 4
  4. g2.1 5
  5. g4.1 3
  6. cat file2
  7. g1.1 2
  8. g1.2 3
  9. g4.1 4
  10. cat file3
  11. g1.2 3
  12. g5.1 3
復制代碼
要求輸出:

  1. g1.1 2 2 -
  2. g1.2 - 3 3
  3. g2.2 4 - -
  4. g2.1 5 - -
  5. g4.1 3 4 -
  6. g5.1 - - 3
復制代碼
實現(xiàn)代碼如下:

  1. awk '{a[ARGIND" "$1]=$2 # ARGIND是當前命令行文件的位置(從0開始),將它和第一列的value作為下標,建立數(shù)組a。
  2.        b[$1]   #將第一列的value作為下標,建立數(shù)組b,目的是在讀完所有文件之后,能得到第一列value的uniqe-list。
  3.         }
  4. END{
  5.         for(i in b) {
  6.                 printf i" "
  7.                 for(j=1;j<=ARGIND;j++) printf "%s ", a[j" "i]?a[j" "i]:"-" #此時的ARGIND值為3.
  8. print ""
  9.                 }
  10.         }' file1 file2 file3
復制代碼
這里是利用awk的內置變量ARGIND來處理完成對文件的處理。關于ARGIND,ARGV,ARGC的使用,大家可以參考:http://www.72891.cn/viewthr ... 0335&from=favorites。
當然,我們也可以利用另外一個內置變量FILENAME來完成相同的任務(大家可以先想想怎么寫),如下:

  1. awk '{a[FILENAME" "$1]=$2;b[$1];c[FILENAME]}END{for(i in b) {printf i" ";for(j in c) printf "%s ", a[j" "i]?a[j" "i]:"-";print""}}' file1 file2 file3
復制代碼
<例2>:對上面的數(shù)據(jù)的格式稍作改動,每個文件的分隔符都一樣的情況,但輸出要求不變:

  1. cat file1
  2. g1.1|2
  3. g2.2|4
  4. g2.1|5
  5. g4.1|3
  6. cat file2
  7. g1.1#2
  8. g1.2#3
  9. g4.1#4
  10. cat file3
  11. g1.2@3
  12. g5.1@3
復制代碼
實現(xiàn)代碼如下:

  1. awk '{a[ARGIND" "$1]=$2
  2. b[$1]
  3. }
  4. END{
  5. for(i in b) {
  6. printf i" "
  7. for(j=2;j<=ARGIND;j+=2) printf "%s ", a[j" "i]?a[j" "i]:"-" # 由于FS的設置也是有對應ARGIND值,所以對ARGIND稍作改動。
  8. print ""
  9. }
  10. }' FS="|" file1 FS="#" file2 FS="@" file3 # 對每個文件分別設置FS的值。
復制代碼
因為這個例子的數(shù)據(jù)比較簡單,我們也可以在BEGIN模塊中完成對FS值設置,如下:

  1. awk 'BEGIN{FS="[|#@]"}{a[ARGIND" "$1]=$2; b[$1]}END{for(i in b) {printf i" ";for(j=1;j<=ARGIND;j++) printf "%s ", a[j" "i]?a[j" "i]:"-"; print ""}}' file1 file2 file3
復制代碼
利用FILENAME 同樣可以解決問題:

  1. awk '
  2. FILENAME=="file1"{FS="|"}    # 設置FS
  3. FILENAME=="file2"{FS="#"}   #設置FS
  4. FILENAME=="file3"{FS="@"}  #設置FS
  5. # 稍顯繁瑣,不過一目了然
  6. {$0=$0}                                   #使FS生效。
  7. {a[ARGIND" "$1]=$2; b[$1]}
  8. END{ for(i in b) {printf i" "; for(j=1;j<=ARGIND;j++) printf "%s ", a[j" "i]?a[j" "i]:"-"; print ""}
  9. }' file1 file2 file3
復制代碼
推薦一個關于數(shù)組處理文件的帖子http://www.chinaunix.net/jh/24/577044.html ,里面有不少例子供大家學習。

7.  文本翻轉或移位:二維或多維數(shù)組的應用
<例1>:

  1. Inputfile
  2. 1 2 3 4 5 6
  3. 2 3 4 5 6 1
  4. 3 4 5 6 1 2
  5. 4 5 6 1 2 3
  6. Outputfile
  7. 4 3 2 1
  8. 5 4 3 2
  9. 6 5 4 3
  10. 1 6 5 4
  11. 2 1 6 5
  12. 3 2 1 6

  13. awk '{
  14.      if (max_nf < NF)
  15.           max_nf = NF # 數(shù)組第一維的長度
  16.      max_nr = NR      # 數(shù)組第二維的長度
  17.      for (x = 1; x <= NF; x++)
  18.           vector[x, NR] = $x #建立數(shù)組vector
  19. }
  20. END {
  21.      for (x = 1; x <= max_nf; x++) {
  22.           for (y = max_nr; y >= 1; --y)
  23.                printf("%s ", vector[x, y])
  24.           printf("\n")
  25.      }
  26. }'
復制代碼
<例2>:來自http://www.72891.cn/viewthr ... &page=1#pid13339226
有兩個文本a和b,要求輸出c文本,合并的規(guī)則是按照第一行的headline(按字母順序)合并文本a和b,空缺按“0”補齊。

  1. cat a.txt
  2. a b c d
  3. 1 2 9 7
  4. 4 5 8 9
  5. 5 3 6 1
  6. cat b.txt
  7. a e f d g
  8. 9 2 4 7 3
  9. 4 3 7 9 4
  10. cat c.txt
  11. a b c d e f g
  12. 1 2 9 7 0 0 0
  13. 4 5 8 9 0 0 0
  14. 5 3 6 1 0 0 0
  15. 9 0 0 7 2 4 3
  16. 4 0 0 9 3 7 4
復制代碼
下面我們來參看并解讀下Tim大師的代碼:

  1. awk '
  2. FNR==1{    #FNR==1,即a和b文本的第一行,這個用的真的很巧妙。
  3.         for(i=1;i<=NF;i++){
  4.                 b[i]=$i    #讀取文本的每個元素存入數(shù)組b
  5.                 c[$i]++}  #另建立數(shù)組c,并統(tǒng)計每個元素的個數(shù)
  6.                 next          #可以理解為,讀取FNR!=1的文本內容。
  7.         }
  8. {k++                                     # 統(tǒng)計除去第一行的文本行數(shù)
  9. for(i=1;i<=NF;i++)a[k","b[i]]=$i  #利用一個二維數(shù)組來保持每個數(shù)字的位置, k,b[i]可以理解為每個數(shù)字的坐標。
  10. }
  11. END{
  12.         l=asorti(c)          #利用asorti函數(shù)對數(shù)組的下標進行排序,并獲取數(shù)組長度,即輸出文件的列數(shù)(NF值)
  13.         for(i=1;i<=l;i++)printf c[i]" " # 先打印第一行,相當于headline。
  14.         print ""
  15.         for(i=1;i<=k;i++){
  16.                 for(j=1;j<=l;j++)printf a[i","c[j]]?a[i","c[j]]" ":"0 " # 打印二維數(shù)組的值。
  17.                 print ""}
  18.         }' a.txt b.txt
復制代碼
8.  選擇性打。
打印某個關鍵字前幾行,以3行為例:

  1. seq 20 |awk '/\<10\>/{for(i=NR-3;i<NR;i++)print a[i%3];exit}{a[NR%3]=$0}'
  2. 7
  3. 8
  4. 9
復制代碼
利用NR取余數(shù),建立數(shù)組,這是一種非常高效的代碼。

9. 通過split函數(shù)建立數(shù)組:數(shù)組的下標為從1開始的數(shù)字。

  1. split(s, a [, r]) # s:string, a:array name,[,r]:regular expression。
  2. echo 'abcd' |awk '{len=split($0,a,"");for(i=1;i<=len;i++) print "a["i"] = " a[i];print "length = " len}'
  3. a[1] = a
  4. a[2] = b
  5. a[3] = c
  6. a[4] = d
  7. length = 4
復制代碼
10. awk數(shù)組使用的小技巧和需要避免的用法:

<1> 嵌套數(shù)組:

  1. awk 'BEGIN{a[1]=3;b[1]=1;print a[b[1]]}'
  2. 3
復制代碼
<2> 下標設為變量或函數(shù):

  1. awk 'BEGIN{s=123;a[substr(s,2)]=substr(s,1,1);for(i in a)print "index : "i"\nvalue : "a[i]}'
  2. index : 23
  3. value : 1
復制代碼
<3> 不可以將數(shù)組名作為變量使用,否則會報錯:

  1. awk 'BEGIN{a["1"] = 3; delete a;a=3;print a}'  #即使你已經(jīng)使用了delete函數(shù)。
  2. awk: fatal: attempt to use array `a' in a scalar context
復制代碼
<4> 數(shù)組的長度:

  1. length(array)  
復制代碼
<5> match 函數(shù)也可以建立數(shù)組(你知道么?,版本要求高于gawk 3.1.2)

  1. echo "foooobazbarrrrr |
  2. gawk '{ match($0, /(fo+).+(bar*)/, arr)  #匹配到的部分自動賦值到arr中,下標從1開始
  3.           print arr[1], arr[2]
  4.           print arr[1, "start"], arr[1, "length"]  #二維數(shù)組arr[index,"start"]值=RSTART
  5.           print arr[2, "start"], arr[2, "length"]  #二維數(shù)組arr[index,"length"]值=RLENGTH
  6.           }'
  7. foooo barrrrr
  8. 1 5
  9. 9 7
復制代碼
<6>想到過用split清空數(shù)組么?

  1. awk 'BEGIN{
  2. split("abc",array,"")
  3. print "array[1] = "array[1],"\narray[2] = "array[2],"\narray[3] = "array[3]
  4. split("",array)
  5. print "array[1] = "array[1],"\narray[2] ="array[2],"\narray[3] ="array[3]
  6. }'
  7. array[1] = a
  8. array[2] = b
  9. array[3] = c
  10. array[1] =
  11. array[2] =
  12. array[3] =
復制代碼

評分

參與人數(shù) 3可用積分 +11 收起 理由
expert1 + 4 居然還有我寫的鏈接呵呵!
xiaopan3322 + 5 可惜沒權限加精華……
waker + 2 感謝分享

查看全部評分

論壇徽章:
33
ChinaUnix元老
日期:2015-02-02 08:55:39CU十四周年紀念徽章
日期:2019-08-20 08:30:3720周年集字徽章-周	
日期:2020-10-28 14:13:3020周年集字徽章-20	
日期:2020-10-28 14:04:3019周年集字徽章-CU
日期:2019-09-08 23:26:2519周年集字徽章-19
日期:2019-08-27 13:31:262016科比退役紀念章
日期:2022-04-24 14:33:24
2 [報告]
發(fā)表于 2011-04-30 10:16 |只看該作者
感謝樓主的無私奉獻

論壇徽章:
2
射手座
日期:2014-10-10 15:59:4715-16賽季CBA聯(lián)賽之上海
日期:2016-03-03 10:27:14
3 [報告]
發(fā)表于 2011-04-30 10:28 |只看該作者
回復 2# Shell_HAT


    說感謝的應該是我,我在CU學到很多東西,非常感謝各位老大們的支持和幫助啊

論壇徽章:
1
摩羯座
日期:2014-12-29 15:59:36
4 [報告]
發(fā)表于 2011-04-30 10:44 |只看該作者

論壇徽章:
0
5 [報告]
發(fā)表于 2011-04-30 11:06 |只看該作者
好文 學習了!

論壇徽章:
0
6 [報告]
發(fā)表于 2011-04-30 15:13 |只看該作者
2. 計算總數(shù)(sum),如:

    awk  '{name[$0]+=$1};END{for(i in name) print  i, name[i]}'
這個也是去重吧?

論壇徽章:
16
IT運維版塊每日發(fā)帖之星
日期:2015-08-24 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2015-10-14 06:20:00IT運維版塊每日發(fā)帖之星
日期:2015-10-25 06:20:00IT運維版塊每日發(fā)帖之星
日期:2015-11-06 06:20:00IT運維版塊每日發(fā)帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT運維版塊每日發(fā)帖之星
日期:2016-04-15 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-21 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2016-08-16 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運維版塊每日發(fā)帖之星
日期:2015-08-14 06:20:00
7 [報告]
發(fā)表于 2011-04-30 20:59 |只看該作者
回復 3# yinyuemi


    居然有個鏈接是我之前寫的,呵呵,考古挖墳了一下

論壇徽章:
1
雙子座
日期:2013-10-17 00:46:45
8 [報告]
發(fā)表于 2011-05-01 01:18 |只看該作者

論壇徽章:
2
射手座
日期:2014-10-10 15:59:4715-16賽季CBA聯(lián)賽之上海
日期:2016-03-03 10:27:14
9 [報告]
發(fā)表于 2011-05-02 01:45 |只看該作者
回復 6# fangtong2008


    恩,可以,因為數(shù)組下標是沒有重復的

論壇徽章:
0
10 [報告]
發(fā)表于 2011-05-02 12:39 |只看該作者
好帖必須頂起來~
其實,來到這里,給我的收獲是非常,非常,非常…… …… ……大
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP