awk同時處理多個文件


關於awk的多文件處理:

awk的數據輸入有兩個來源,標准輸入和文件,后一種方式支持多個文件,如
1、shell的Pathname Expansion方式:awk '{...}' *.txt # *.txt先被shell解釋,替換成當前目錄下的所有*.txt,如當前目錄有1.txt和   2.txt,則命令最終為awk '{...}' 1.txt 2.txt
2、直接指定多個文件: awk '{...}' a.txt b.txt c.txt ...
awk對多文件的處理流程是,依次讀取各個文件內容,如上例,先讀a.txt,再讀b.txt....

那么,在多文件處理的時候,如何判斷awk目前讀的是哪個文件,而依次做對應的操作呢?
1、當awk讀取的文件只有兩個的時候,比較常用的有兩種方法
一種是awk 'NR==FNR{...}NR>FNR{...}' file1 file2 或awk 'NR==FNR{...}NR!=FNR{...}' file1 file2
另一種是 awk 'NR==FNR{...;next}{...}' file1 file2
了解了FNR和NR這兩個awk內置變量的意義就很容易知道這兩種方法是如何運作的

QUOTE:
FNR The input record number in the current input file. #已讀入當前文件的記錄數
NR The total number of input records seen so far. #已讀入的總記錄數
next Stop processing the current input record. The next input record is
read and processing starts over with the first pattern in the AWK
program. If the end of the input data is reached, the END block(s),
if any, are executed.

對於awk 'NR==FNR{...}NR>FNR{...}' file1 file2
讀入file1的時候,已讀入file1的記錄數FNR一定等於awk已讀入的總記錄數NR,因為file1是awk讀入的首個文件,故讀入file1時執行前一個命令塊{...}
讀入file2的時候,已讀入的總記錄數NR一定>讀入file2的記錄數FNR,故讀入file2時執行后一個命令塊{...}

對於awk 'NR==FNR{...;next}{...}' file1 file2
讀入file1時,滿足NR==FNR,先執行前一個命令塊,但因為其中有next命令,故后一個命令塊{...}是不會執行的
讀入file2時,不滿足NR==FNR,前一個命令塊{..}不會執行,只執行后一個命令塊{...}

2、當awk處理的文件超過兩個時,顯然上面那種方法就不適用了。因為讀第3個文件或以上時,也滿足NR>FNR (NR!=FNR),顯然無法區分開來。
所以就要用到更通用的方法了:
1、ARGIND 當前被處理參數標志: awk 'ARGIND==1{...}ARGIND==2{...}ARGIND==3{...}... ' file1 file2 file3 ...
2、ARGV 命令行參數數組: awk 'FILENAME==ARGV[1]{...}FILENAME==ARGV[2]{...}FILENAME==ARGV[3]{...}...' file1 file2 file3 ...
3、把文件名直接加入判斷: awk 'FILENAME=="file1"{...}FILENAME=="file2"{...}FILENAME=="file3"{...}...' file1 file2 file3 ... #沒有前兩種通用

舉例:


有兩個文件a.txt 和 b.txt
a.txt中第一列和第二列數字都有重復,格式如下:
20000401 100000999
20000401 100002999
20000401 100007999
20000401 100013999
20100503 100000999
20100503 400002999
20100503 100007999
20100503 400013999

b.txt中第一列數字唯一,不重復,格式如下:
100000999 123
100002999 456
100007999 137
100013999 253
400002999 394
400013999 672

想要連接兩個文件形成c.txt,形成的c.txt格式如下:
20000401 100000999 123
20000401 100002999 456
20000401 100007999 137
20000401 100013999 253
20100503 100000999 123
20100503 400002999 394
20100503 100007999 137
20100503 400013999 672

awk 'NR==FNR{a[$1]=$2} NR>FNR{print $0,a[$2]}' b.txt a.txt
awk 'NR==FNR{a[$1]=$2;next}{print $0,a[$2]}' b.txt a.txt

 

又有如下需求:

我有兩個的檔案:
 a.txt (內容很普通,就是正常文本)
 asaff
 adfg
 dgfjh
 djghalhg
 
b.txt (因為a中有些行是錯的,所以修改了,格式為:行號+修改內容)
 2:asaffnew
 4:hgitsh
 
想根據 b 檔案的行號替換 a.txt 的相關行,請問怎樣處理?

awk -F: 'NR==FNR{a[$1]=$2;next}FNR in a{print a[FNR];next}1' b.txt a.txt
awk -F: 'NR==FNR{a[$1]=$2;next};FNR in a{$0=a[FNR]}1' b.txt a.txt

這個1有打印當前整行的意思。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM