仕様の完成:
- 行番号はファイルに物理的に存在しますか? はい
- File1 のエントリが File2 のエントリと一致することを示す列の組み合わせはどれですか? 行番号
- 見出し行はファイルに物理的に存在しますか? いいえ(ただし、後で気が変わります)
- ファイル内のデータはソートされていますか? いいえ
- File1 には存在するが File2 には存在しないレコードはどのように処理されますか? 指定されていませんが、おそらく 3 番目の出力ファイルが必要です。
答えは「削除されたレコード」の問題を無視します。
質問は、このロジックが File2 に挿入されたレコードを見つけることを観察します。
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";
}
}
}'
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 の演習です。