標籤:style http color os io strong ar for 檔案
awk 處理多個檔案
awk處理多個檔案的方式是:一個一個的處理。
Demo1
$ cat $ cat 1.txt a 1 b 2c 3d 4$ cat 2.txt b 5 c 6d 7e 8$ awk ‘{print $0}‘ 1.txt 2.txta 1 b 2c 3d 4b 5 c 6d 7e 8
那怎麼分辨當前處理的是哪一個檔案呢?先看一下awk的內建變數有哪些。
FILENAME: 當前輸入的檔案名稱字
FNR: 當前輸入檔案的記錄數
NR: awk開始工作處理的總的記錄數
NF: 目前記錄的欄位數
FS: 輸入欄位分割符
OFS: 輸出欄位分隔符號
RS: 輸入記錄分隔字元
ORS: 輸出記錄分隔字元
ARGIND: 當前處理參數的標誌,對於Demo1中的 1.txt 該值是1,2.txt是2
ARGV: 命令列參數數組,對於Demo1是,ARGV[1]="1.txt" ARGV[2]="2.txt"
ARGC: 命令列參數的個數
對於兩個檔案的時候,我們可以這麼處理:
方法1 -- by FNR & NR
由上可知,只有處理第一個檔案的時候FNR才會等於NR,所以可以如下所示:
$ awk ‘FNR==NR{print $0}FNR!=NR{print $0}‘ 1.txt 2.txt $ awk ‘FNR==NR{print $0}FNR<NR{print $0}‘ 1.txt 2.txt
方法2 -- by FILENAME
$ awk ‘FILENAME=="1.txt"{print "file1:"$1}FILENAME=="2.txt"{print "file2:" $2}‘ 1.txt 2.txt
方法3 -- by FILENAME & ARGV
方法2不是很靈活,因為下次換輸入的時候,整個命令列都要改一下,很麻煩,其實可以通過ARGV來擷取輸入的變數名,awk把所有的輸入變數都是存放在數組ARGV中。所以可以根據ARGV來擷取輸入的檔案名稱,提高命令列的靈活性。
$ awk ‘FILENAME==ARGV[1]{print "file1:"$1}FILENAME==ARGV[2]{print "file2:" $2}‘ 1.txt 2.txt
方法4 -- by ARGIND
方法3貌似也有點複雜,可以通過ARGIND來實現。
$ awk ‘ARGIND==1{print "file1:"$1}ARGIND==2{print "file2:" $2}‘ 1.txt 2.txt
上面四個的運行結果都是:
file1:a 1 file1:b 2file1:c 3file1:d 4file2:b 5 file2:c 6file2:d 7file2:e 8
對於處理兩個以上檔案的時候,方法1是不行的,可以用方法2,3,4來實現。
應用舉例:
Demo2: 比較兩個檔案中第一列相同的行,並把檔案1中相同的行print出。 對於Demo1中的檔案1,檔案2,最後輸出:
b 2c 3d 4
實現方式:
$ awk ‘FNR==NR{a[$1]=$0}FNR!=NR{print a[$1]}‘ 1.txt 2.txt
先將1.txt做一個字典映射,key是第一列,value是一行,然後取2.txt的第一列為key取字典中的value即可。
Demo3: 借鑒一下別人的例子:比較 file1的1-4字元 和 file2的2-5 字元,如果相同,將file2 的第二列 與 file1 合并 file3(http://bbs.chinaunix.net/thread-577044-1-1.html)
$ cat file10011AAA 200.00 20050321 0012BBB 300.00 20050621 0013DDD 400.00 20050622 0014FFF 500.00 20050401 $ cat file2I0011 11111 I0012 22222 I0014 55555 I0013 66666 $ awk ‘NR==FNR{a[substr($1,1,4)]=$0}NR!=FNR&&a[b=substr($1,2,5)]{print a[b] $2}‘ file1 file20011AAA 200.00 20050321 111110012BBB 300.00 20050621 222220014FFF 500.00 20050401 555550013DDD 400.00 20050622 66666
這裡主要要注意&&a[b=substr($1,2,5)]這塊,相當於是一個前置條件,即file2的2:5字元如果沒有出現就不會執行後面的print語句。
Demo4: 輸入下面兩個檔案
$ cat 1.txt 10/05766798607,11/20050325191329,29/0.1,14/05766798607 10/05767158557,11/20050325191329,29/0.08,14/05767158557 $ cat 2.txt 05766798607 05766798608 05766798609
輸出:
10/05766798607,11/20050325191329,29/0.1,14/05766798607
實現方法:
$ awk -F‘[/,]‘ ‘NR==FNR{a[$0]=$0}FNR!=NR{if ($2 in a) print $0}‘ 2.txt 1.txt$ awk ‘BEGIN{FS="[/,]"}NR==FNR{a[$0]}NR!=FNR{if ($2 in a) print $0}‘ 2.txt 1.txt
前後兩個執行的結果是一樣的,-F 和 FS 的效果是一樣的,都是設定輸入分隔字元
awk 處理多個檔案