Text-Processing
僅逐行比較特定列上的兩個文件
if i in [2,4,7]
awk 中for 循環內部的語法是什麼?還有任何想法如何在下面的程式碼中實現。謝謝輸入 :
$ cat f1 col1,col2,col3,col4,col5,col6,col7 col11,col12,col13,col14,col15,col16,col17 $ cat f2 col1,col2,col03,col4,col5,col06,col7 col11,col12,col13,col14,col015,col16,col17 $ awk -F, ' NR==FNR { a[FNR][0]=$0 #populate base file records for(i=1;i<=NF;i++) a[FNR][i]=$i #populate base file fields next } { for(i=1;i<=NF;i++) { #if(i in [2,4,7]) <***How to chieve this column in list of values*** > #continue; if($i!=a[FNR][i]) { printf "Line#%d, column:%d is different in two files.\n",FNR,i # ***<TODO print record from first file and second file after printing all mismatch columns>*** } } }' f1 f2
預期輸出:
Line#1, column:3 is different in two files. Line#1, column:6 is different in two files. col1,col2,col3,col4,col5,col6,col7 col1,col2,col03,col4,col5,col06,col7> Line#2, column:5 is different in two files. col11,col12,col13,col14,col15,col16,col17 col11,col12,col13,col14,col015,col16,col17>
基本上,您正在對兩個文件和特定列(不包括某些列)進行逐行比較;也就是說,您可以使用 GNU
awk
來支持單詞邊界\<
&\>
:awk -F, -v skip='2,4,7' 'BEGIN{ filetwo=ARGV[1]; ARGV[1]=""; };{ getline lf2 <filetwo; split(lf2, arr, ","); for (i=1; i<=NF; i++) { if ( (skip !~ "\\<"i"\\>") && $i!=arr[i] ) { print "Line#"FNR, "Column#" i " is different in two files."; mismatch=1; }; }; }; mismatch { print $0; print lf2; mismatch=0; };' file2 file1
或在任何
awk
版本中:awk -F, -v skip_cols='2,4,7' ' BEGIN{ filetwo=ARGV[1]; ARGV[1]=""; split(skip_cols, skip, ","); };{ getline lf2 <filetwo; split(lf2, arr, ","); for (i=1; i<=NF; i++) { if ( !(i in skip) && $i!=arr[i] ) { print "Line#"FNR, "Column#" i " is different in two files."; mismatch=1; }; }; }; mismatch { print $0; print lf2; mismatch=0; };' file2 file1
解釋程式碼:
首先執行一次,然後才
awk
想讀取任何輸入。
- 使用 ARGV ,
filetwo=ARGV[1];
:讀取傳遞給命令的第二個參數(即
file2
)並將其保存到filetwo
變數中;第一個參數ARGV[0]
是awk本身,第三個參數ARGV[2]
是file1
.
- 在我們讀取參數的值之後,
ARGV[1]=""
我們取消設置它的值,所以 awk 不會找到該參數 (file2
) 進行讀取。skip="2 4 7";
:我們定義了一個變數(參見賦值表達式)
skip
並設置了我們以後要忽略的列號。我們正在從 file2 中讀取一行並將其分配給變數
lf2
(請注意,上面的filetwo
變數現在包含我們從中讀取的第二個參數的名稱ARGV[1]
)我們將從file2中讀取的行拆分為
lf2
逗號字元變數,
並儲存到名為的數組中arr.
;現在該行的每個欄位都由arr[1]
(第一個欄位),arr[2]
(第二個欄位),arr[3]
(第三個)等定址。
在
for-loop
聲明中,我們檢查以下兩件事:
- 在變數值
i
中看! ~
不到指示列號的skip
變數值(skip !~ "\\<"i"\\>"
;\<
並且\>
是單詞邊界錨,awk
特定於 GNU,因此i=2
不會匹配22
);下一個- 檢查 file1 中列的值是否與具有相同索引的 file2 的同一列不相等:
$i!=arr[i]
;如果這些不同,則列印不匹配的行號FNR
和差異列索引i
,並設置一個控制變數mismatch=1
。
mismatch { print ... }``lf2
:僅當檢測到不匹配並且在語句mismatch
中設置了變數時,才列印 file1 中的兩行,然後是 file2 中的行;if
並為下一行重置變數mismatch=0
。