特定の列でのみ2つのファイルを行ごとに比較します。

特定の列でのみ2つのファイルを行ごとに比較します。

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>

ベストアンサー1

デフォルトでは、2つのファイルを行ごとに比較し、特定の列を除外すると、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

コードを説明してください。

  • これBEGIN { ... }詰まった:これは、
    入力を読み取る前に最初に行われます。awk

    • ARGVの使用filetwo=ARGV[1];
      コマンドに渡された2番目の引数(例:)file2を読み、それをfiletwo変数に保存ARGV[0]します。アッそれ自体、3番目ARGV[2]はですfile1
    • パラメータ値を読み取った後、その値を設定解除するため、awkは読み取るパラメータをARGV[1]=""見つけることができません()。file2
    • skip="2 4 7";a:
      私たちは変える(望むより割り当て式skip無視したい列番号を設定します。
  • getline注文する- バラよりgetlineファイルの変数の使用
    file2から1行を読み取り、それを変数に割り当てますlf2(今、上記の変数には、filetwo2番目の引数の名前が含まれていますARGV[1])。

  • split()機能
    読み出し線を分割するファイル2これはlf2コンマ文字の変数にあり、名前付き配列に格納されます。行の各フィールド,は、(最初​​のフィールド)、(2番目のフィールド)、(3番目)などでアドレスarr.指定されます。arr[1]arr[2]arr[3]

  • 以内にfor-loop氏名次の2つを確認します。

    • 列番号を表す変数値は変数値には表示されませんi(; GNU固有の単語境界アンカーなので一致しません).! ~skipskip !~ "\\<"i"\\>"\<\>awki=222
    • file1 の列値が、同じ索引を持つ file2 の同じ列と同じであることを確認します。$i!=arr[i];等しくない場合は、一致しない行番号FNRと差分列インデックスを印刷し、i制御変数を設定しますmismatch=1
  • mismatch { print ... }lf2:不一致が検出され、文に変数が設定され、次の行の変数がリセットされた場合にのみ、mismatchfile1の2行を印刷してから、file2の行を印刷します。ifmismatch=0

おすすめ記事