轉載:https://www.cnblogs.com/irockcode/p/7044722.html
NR,表示awk開始執行程式后所讀取的資料行數.
FNR,與NR功用類似,不同的是awk每打開一個新檔案,FNR便從0重新累計.
下面看兩個例子:
1,對于單個檔案NR 和FNR 的 輸出結果一樣的 :
| 1 2 3 4 5 6 7 8 9 |
# awk '{print NR,$0}' file1
1 a b c d
2 a b d c
3 a c b d
#awk '{print FNR,$0}' file1
1 a b c d
2 a b d c
3 a c b d
|
2,但是對于多個檔案 :
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# awk '{print NR,$0}' file1 file2
1 a b c d
2 a b d c
3 a c b d
4 aa bb cc dd
5 aa bb dd cc
6 aa cc bb dd
# awk '{print FNR,$0}' file1 file2
1 a b c d
2 a b d c
3 a c b d
1 aa bb cc dd
2 aa bb dd cc
3 aa cc bb dd
|
在看一個例子關于NR和FNR的典型應用:
現在有兩個檔案格式如下:
| 1 2 3 4 5 6 7 8 |
#cat a
張三|000001
李四|000002
#cat b
000001|10
000001|20
000002|30
000002|15
|
想要得到的結果是將用戶名,帳號和金額在同一行列印出來,如下:
張三|000001|10
張三|000001|20
李四|000002|30
李四|000002|15
執行如下代碼
| 1 |
#awk -F \| 'NR==FNR{a[$2]=$0;next}{print a[$1]"|"$2}' a b
|
注釋:
由NR=FNR為真時,判斷當前讀入的是第一個檔案a,然后使用{a[$2]=$0;next}
回圈將a檔案的每行記錄都存入陣列a,并使用$2第2個欄位作為下標參考.
由NR=FNR為假時,判斷當前讀入了第二個檔案b,然后跳過{a[$2]=$0;next},
對第二個檔案cdr的每一行都無條件執行{print a[$1]"|"$2},
此時變數$1為第二個檔案的第一個欄位,與讀入第一個檔案時,采用第一個檔案第二個欄位$2為陣列下標相同.
因此可以在此使用a[$1]參考陣列,
=========================================================================
下面是CU大神jason680的詳細程序分析
awk -F'|' 'NR==FNR{a[$2]=$0;next}{print a[$1] FS $2}' a b
There is no BEGIN block, and FS="|" by -F'|' argument
沒有開始模塊,直接識別-F選項,加引數
start to first file 'a'
從a檔案的第一行開始
1. read file a line 1 and get data 張三|000001
讀取檔案a的第一行,得到資料
A: $0=張三|000001
B: $1=張三
C: $2=000001
NR and FNR are the same equal to 1, and run NR=FNR block
此時,NR與FNR的值相等都為1,執行NR=FNR模塊
NR==FNR{a[$2]=$0;next}
A: a[$2]=$0
a[000001]=張三|000001
B: next
next cycle and get next line data
2. read file a line 2 and get data 李四|000002
讀取檔案a的第二行,得到資料
A: $0=李四|000002
B: $1=李四
C: $2=000002
NR and FNR are the same equal to 2, and run NR=FNR block
此時,NR與FNR的值相等都為2,執行NR=FNR模塊
NR==FNR{a[$2]=$0;next}
A: a[$2]=$0
a[000002]=李四|000002
B: next
next cycle and get next line data
end of the file a, and get next file b data
讀完檔案a,然后讀取下一個檔案b的資料
3. read file b line 1, and get data 000001|10
讀取檔案b的第一行,然后得到資料
A: $0=000001|10
B: $1=000001
C: $2=10
now, NR is 3 and FNR is 1, they are not eqaul
此時,NR與FNR的值不同,不執行NF=FNR模塊,執行下一個模塊{print a[$1] FS $2}
and didn't run NR=FNR block,
and run next block {print a[$1] FS $2}
a[$1] => a[000001] => 張三|000001
FS => |
$2 => 10
you will see the output
張三|000001|10
4. read file b line 2, and get data 000001|20
A: $0=000001|20
B: $1=000001
C: $2=20
NR is 4 and FNR is 2, they are not eqaul
and didn't run NR=FNR block,
and run next block {print a[$1] FS $2}
a[$1] => a[000001] => 張三|000001
FS => |
$2 => 20
you will see the output
張三|000001|20
cycle to read the file b
5. read file b line 3, and get data 000002|30
...
output==> 李四|000002|30
6. read file b line 4, and get data 000002|15
...
output==> 李四|000002|15
補充:
找出兩個檔案之間的不同部分
awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]' 1.txt 2.txt
awk 'NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}' 1.txt 2.txt
找出兩個檔案之間的相同部分
awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]' 1.txt 2.txt
awk 'NR==FNR{a[$0]}NR>FNR{ if($1 in a) print $0}' 1.txt 2.txt
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/110690.html
標籤:Linux
