同じ行と列の数、同じレコードの順序を持つ2つのファイルを比較したいと思います。列の値に違いがある場合は、これを強調したいと思います。
file A
:
1,kolkata,19,ab
2,delhi,89,cd
3,bangalore,56,ef
file B
:
1,kolkata,21,ab
2,mumbai,89,gh
3,bangalore,11,kl
列を1
主キーとみなすと、他の列と違いがあります。私はこれらの違いを強調したいと思います。
出力形式は次のとおりです(不明)。
record_number, columns_with_diff
1 3
2 2,4
3 3,4
私の問題をdiff
解決できますか?comm
それでは、正確なコマンドは何ですか?
答え1
それはすべてです。各行の末尾に追加のカンマがある場合は、いくつかのスタイルの問題があります。
awk '
BEGIN{ FS=","; ORS="" }
{
# read line from secondary file
getline aux < "file2"
split(aux,f2,",")
# print current line number
print NR" "
# process each field in current line
for(i=1; i<=NF; i++) {
if ($i!=f2[i]) {
print i","
}
}
print "\n"
}
' file1
出力:
1 3,
2 2,4,
3 3,4,
答え2
以下を使用すると、これを簡単に実行できますperl
。
$ perl -F',' -anle '
BEGIN{
print "record_number, columns_with_diff";
$" = ",";
}
if (!defined($h{$.})) {
@{$h{$.}}{0..$#F} = @F[0..$#F];
} else {
@diff = grep { $h{$.}{$_} ne $F[$_] } 0..$#F;
print "$.\t\t@{[map {$_+1} @diff]}";
}
close ARGV if eof;
' file1 file2
record_number, columns_with_diff
1 3
2 2,4
3 3,4
これを行うには、入力から空白行を削除する必要があります。
説明する
ブロックは
BEGIN
出力タイトルを印刷し、リスト区切り記号を次のように設定します。,
@{$h{$.}}{0..$#F} = @F[0..$#F]
:ハッシュのハッシュを生成します。ここで、最初のハッシュのキーは行番号であり、各子ハッシュのキーはフィールドインデックスから1を引いた値であり、値はそのフィールドに対応する値である。
ここでは、ハッシュスライシングを使用してハッシュのハッシュに値をすばやく割り当てます。
Data::Dumper
hash のハッシュを印刷すると、%h
次のような内容が表示されます。
VAR1 = {
'2' => {
'2' => '89',
'0' => '2',
'1' => 'delhi',
'3' => 'cd'
},
'3' => {
'1' => 'bangalore',
'3' => 'ef',
'0' => '3',
'2' => '56'
},
'1' => {
'3' => 'ab',
'1' => 'kolkata',
'0' => '1',
'2' => '19'
}
};
%h
()を作成するとif (!defined($h{$.}))
(処理が完了したことを意味しますfile1
)、現在の行の各フィールドをのコア値と比較して、他のすべての%h
インデックスを配列に保存します@diff
。map {$_+1} @diff
配列インデックスは0から始まり、列番号は1から始まり、列番号を回復します。close ARGV if eof
カウンターを復元します$.
。