Text-Processing

僅逐行比較特定列上的兩個文件

  • November 27, 2020

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>

基本上,您正在對兩個文件和特定列(不包括某些列)進行逐行比較;也就是說,您可以使用 GNUawk來支持單詞邊界\<& \>

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想讀取任何輸入。

讀取傳遞給命令的第二個參數(即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

引用自:https://unix.stackexchange.com/questions/621138