2013-03-29 28 views
0

欄比較,我有兩個文件列在UNIX

文件1

Row Col1 Col2 Col3 Col4 
1  A  B C  D 
2  E  F G  H 

文件2

Row Col1 Col2 Col3 Col4 
1  A  Z C  D 
2  E  F Y  H 
3  M  N O  P 

要求是列比較有逐行然後列。有了這兩個輸出文件需要創建。 首先將file2中的第3行指出這些行在file2中是新的。 第二個文件都會有這樣的輸出:

FileName Row ColName ColValue 
File1  1  Col2 B (--this is old value) 
File2  1  Col2 Z (--this is new value) 

File1  2  Col3 G 
File2  2  Col3 Y 

我們得到這些缺少文件1行,但存在於文件2可以通過

awk 'NR==FNR{a[$1]++;next;}!($0 in a)' file2 file1 

,但不知道如何生成的第二輸出文件來完成。

+0

這是否意味着最後一行輸出中的File2?行號是否存在於文件中?什麼組合的列告訴你,File1中的條目與File2中的條目匹配?它可能只是行號,行號加上col1,或行號加上col1和col4,或者只是col1,或col1和col4。標題行是否存在於文件中?文件中的數據是否已分類? –

回答

1

完成規格:

  • 是行號實際存在的文件?
  • 什麼組合的列告訴你,File1中的條目與File2中的條目匹配? 行號
  • 標題行是否實際存在於文件中? 否(但我們稍後改變主意)
  • 文件中的數據是否已排序? 假設沒有
  • 如何處理File1中的記錄但不處理File2中的記錄? 未指定,但可能需要第三個輸出文件。

答案會忽略'已刪除記錄'的問題。

的問題指出,這個邏輯發現插入文件2中的記錄:

awk 'NR==FNR{a[$1]++;next;}!($0 in a)' file2 file1 

這是接近正確;它應該是!($1 in a)。需要明確的打印才能將輸出發送到文件。對於邏輯的其餘部分,我們可以很容易發現在字段的變化:

awk 'NR == FNR { a[$1] = $0; next } 
    !($1 in a) { print $0 > "ofile.1"; next } 
       { split(a[$1], old); 
        for (i = 2; i <= NF; i++) 
        { 
         if ($i != old[i]) 
         { 
          format = "%-8s %4d %d %s\n" 
          printf format, "File1", $1, i, $i  > "ofile.2"; 
          printf format, "File2", $1, i, old[i] > "ofile.2"; 
         } 
        } 
       }' 

這在給定的假設下產生合理的輸出(標題行不存在)。事實上,如果標題行存在,那麼你必須捕捉和使用它們(文件名太):

awk 'FNR == 1 { file[++num] = FILENAME; for (i = 1; i <= NF; i++) head[i] = $i; next } 
    NR == FNR { a[$1] = $0; next } 
    !($1 in a) { print $0 > "ofile.1"; next } 
       { split(a[$1], old); 
        for (i = 2; i <= NF; i++) 
        { 
         if ($i != old[i]) 
         { 
          format = "%-8s %4d %-4s %s\n" 
          printf format, file[1], $1, head[i], $i  > "ofile.2"; 
          printf format, file[2], $1, head[i], old[i] > "ofile.2"; 
         } 
        } 
       }' 

,並獲得有關第二輸出文件的正確標題,你需要做出一些更小的調整:

awk 'NR == 1 { printf "%-8s %4s %-7s %s\n", "Filename", "Row", "Colname", "Colvalue" > "ofile.2" } 
    FNR == 1 { file[++num] = FILENAME; for (i = 1; i <= NF; i++) head[i] = $i; next } 
    NR == FNR { a[$1] = $0; next } 
    !($1 in a) { print $0 > "ofile.1"; next } 
       { split(a[$1], old); 
        for (i = 2; i <= NF; i++) 
        { 
         if ($i != old[i]) 
         { 
          format = "%-8s %4d %-7s %s\n" 
          printf format, file[1], $1, head[i], $i  > "ofile.2"; 
          printf format, file[2], $1, head[i], old[i] > "ofile.2"; 
         } 
        } 
       }' File1 File2 

從該輸出樣本是:

OFILE。1

3  M  N O  P 

ofile.2

Filename Row Colname Colvalue 
File1  1 Col2  Z 
File2  1 Col2  B 
File1  2 Col3  Y 
File2  2 Col3  G 

如果你想在每條記錄後的空白行,這是一個微不足道的修改 - 鍛鍊的OP。