特定の列でのみ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

答え2

私が正しく理解した場合:

  • すべてのフィールドに対してforループを実行しようとしています。 for(i=1;i<=NF;i++) { ... }
  • 内部:iが4つの値のいずれかである場合はスキップしたいと思います。 (awkでは、「続き」は現在のforループの残りの部分をバイパスし、次の反復に進みます。

簡単な方法:フィールドをスキップするには、次の技術を使用できます。

BEGIN { skip[2]++; skip[3]++; skip[22]++; skip[23]++ }

....
 for(i=1;i<=NF;i++) {
   if (i in skip) { continue ; rem="Will skip for values defined in skip array indexes" }
   ...

BEGINセクションで "skip"を定義する代わりに、スキップインデックスが4つ(1行に1つ)あるファイルがあり、NR = = FNR条件を使用してファイルを読み取り、このスキップの配列で埋めることもできます。 NR!= FNRの場合(ソースファイルを読むとき)、上記の方法を使用してフィールドをスキップできます。

答え3

$ cat tst.awk
BEGIN {
    FS=","
    split("2,4,7",tmp)
    for (i in tmp) {
        skipFldNrs[tmp[i]]
    }
}
NR==FNR {
    old[FNR] = $0
    next
}
FNR == 1 {
    for (fldNr=1; fldNr<=NF; fldNr++) {
        if ( !(fldNr in skipFldNrs) ) {
            chkFldNrs[++numToChk] = fldNr
        }
    }
}
old[FNR] != $0 {
    split(old[FNR],o)
    for (i=1; i<=numToChk; i++) {
        fldNr = chkFldNrs[i]
        if ( o[fldNr] != $fldNr ) {
            printf "Line#%d, column:%d is different in two files (\"%s\" vs \"%s\").\n", FNR, fldNr, o[fldNr], $fldNr
        }
    }
}

$ awk  -f tst.awk f1 f2
Line#1, column:3 is different in two files ("col3" vs "col03").
Line#1, column:6 is different in two files ("col6" vs "col06").
Line#2, column:5 is different in two files ("col15" vs "col015").

関連情報