
Ich möchte zwei Dateien mit gleicher Zeilen- und Spaltenanzahl und Datensätzen in gleicher Reihenfolge vergleichen. Ich möchte lediglich die Unterschiede in den Spaltenwerten hervorheben, falls welche vorhanden sind.
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
Wenn wir die Spalte 1
als Primärschlüssel betrachten, gibt es Unterschiede in anderen Spalten. Ich möchte diese Unterschiede hervorheben.
Das Ausgabeformat könnte sein (nicht sicher):
record_number, columns_with_diff
1 3
2 2,4
3 3,4
Kann diff
oder comm
kann das mein Problem lösen? Wenn ja, wie lautet der genaue Befehl?
Antwort1
Das wäre es. Nur ein Stilproblem mit dem zusätzlichen Komma am Ende jeder Zeile.
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
Die Ausgabe:
1 3,
2 2,4,
3 3,4,
Antwort2
Einfacher geht es mit 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
Damit dies funktioniert, sollten Sie Leerzeilen in Ihrer Eingabe entfernen.
Erläuterung
Im
BEGIN
Block drucken wir einfach den Header der Ausgabe und setzen dann den Listentrenner auf,
@{$h{$.}}{0..$#F} = @F[0..$#F]
: Wir erstellen einen Hash aus Hashes, wobei die Schlüssel des ersten Hashes die Zeilennummer sind, die Schlüssel jedes Unter-Hashes der Index des Felds minus 1 sind und die Werte Werte sind, die mit diesen Feldern korrespondieren.
Hier verwenden wir ein Hash-Slice, um Hashes von Hashes schnell Werte zuzuweisen.
Wenn Sie Data::Dumper
den Hash der Hashes drucken %h
, sehen Sie ungefähr Folgendes:
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
Wenn wir ( ) erstellt habenif (!defined($h{$.}))
– also die Verarbeitung abgeschlossen habenfile1
– vergleichen wir einfach jedes Feld der aktuellen Zeile mit dem entsprechenden Wert in%h
und speichern alle Indizes, die sich im Array unterscheiden@diff
.map {$_+1} @diff
Stellen Sie die Spaltennummer wieder her, da der Index des Arrays bei 0 und die Spaltennummer bei 1 beginnt.close ARGV if eof
Zähler wiederherstellen$.
.