1
2
3
4
5
6
7
V1 V2 V3 V4 V5
ID1 aa nn zz ii
ID2 ss rr oo ll
ID4 qq mm öö pp
ID5 nn vv bb xx
...
...
1
2
3
4
5
6
7
8
V1 V2 V3 V4 V5 V6
ID1 aa nn zz ii 45
ID3 ff xx yy tt 45
ID4 qq mm öö pp 45
ID6 uu kk nn ff 45
ID7 qq ww ee rr 45
...
...
1
2
3
4
5
6
7
V1 V2 V3 V4 V5 V6
ID1 aa nn zz ii 45
ID2 ss rr oo ll
ID4 qq mm öö pp 45
ID5 nn vv bb xx
...
...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use warnings; use strict; use Data::Dump qw(dump); my %db; # Datenbank my $using = 'V1'; # Spalte fuer JOIN # Daten einlesen, hier aus DATA-Segment for my $table ('table1', 'table2') { my $id_col; while (my $line = <DATA>) { last if $line !~ /\S/; # Spaltennamen incl. Reihenfolge sichern, # Spaltennummer der $using-Spalte ermitteln if (! exists $db{'col_names'}{$table}) { my @cols = split ' ', $line; grep { $id_col = $_ if $cols[$_] eq $using } 0..$#cols; die "$table does not contain col '$using'\n" if ! defined $id_col; @{$db{'col_names'}{$table}} = @cols; next; } my @cols = split ' ', $line; my $id = $cols[$id_col]; # Daten in Datenbanktabelle einlesen $db{$table}{$id} = { map { @{$db{'col_names'}{$table}}[$_] => $cols[$_] } 0..$#cols }; } } # Spaltennamen fuer Differenz-Tabellen und Join-Tabelle erzeugen, # Namen, die nur in table2 vorhanden sind, an join-Spaltennamen anhaengen @{$db{'col_names'}{'not_in_table1'}} = @{$db{'col_names'}{'table2'}}; @{$db{'col_names'}{'not_in_table2'}} = @{$db{'col_names'}{'table1'}}; @{$db{'col_names'}{'table_join'}} = @{$db{'col_names'}{'table1'}}; for my $col (@{$db{'col_names'}{'table2'}}) { if (! grep { $_ eq $col } @{$db{'col_names'}{'table_join'}}) { push @{$db{'col_names'}{'table_join'}}, $col; } } # Daten mergen, Datensaetze aus table2 ueberschreiben die aus table1 for my $id (keys %{$db{'table2'}}) { if (exists $db{'table1'}{$id}) { %{$db{'table_join'}{$id}} = %{$db{'table2'}{$id}}; } else { %{$db{'not_in_table1'}{$id}} = %{$db{'table2'}{$id}}; } } for my $id (keys %{$db{'table1'}}) { if (! exists $db{'table2'}{$id}) { %{$db{'not_in_table2'}{$id}} = %{$db{'table1'}{$id}}; %{$db{'table_join'}{$id}} = %{$db{'table1'}{$id}}; } } # Entkommentieren, um Datenstruktur anzusehen: # dump(%db); # Ausgabe no warnings 'uninitialized'; for my $table ('table_join', 'not_in_table1', 'not_in_table2') { printf( "$table: %d Zeilen\n\n%s\n", scalar(keys %{$db{$table}}), join("\t", @{$db{'col_names'}{$table}}) ); for my $row (sort keys %{$db{$table}}) { printf( "%s\n", join("\t", map { $db{$table}{$row}{$_} } @{$db{'col_names'}{$table}} ) ); } print "\n"; } __DATA__ V1 V2 V3 V4 V5 ID1 aa nn zz ii ID2 ss rr oo ll ID4 qq mm öö pp ID5 nn vv bb xx V1 V2 V3 V4 V5 V6 ID1 aa nn zz ii 45 ID3 ff xx yy tt 45 ID4 qq mm öö pp 45 ID6 uu kk nn ff 45 ID7 qq ww ee rr 45
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
table_join: 4 Zeilen
V1 V2 V3 V4 V5 V6
ID1 aa nn zz ii 45
ID2 ss rr oo ll
ID4 qq mm öö pp 45
ID5 nn vv bb xx
not_in_table1: 3 Zeilen
V1 V2 V3 V4 V5 V6
ID3 ff xx yy tt 45
ID6 uu kk nn ff 45
ID7 qq ww ee rr 45
not_in_table2: 2 Zeilen
V1 V2 V3 V4 V5
ID2 ss rr oo ll
ID5 nn vv bb xx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#!/usr/bin/perl use strict; use warnings; use IO::File; use Data::Dumper; # Tabellen auf hash lesen: t1.txt, t2.txt my $tab1 = tabContent('t1.txt'); my $tab2 = tabContent('t2.txt'); # mergen my %result = (%{$tab1}, %{$tab2}); # Keys in {1} kriegen Update von {2] print Dumper \%result; sub tabContent{ my $file = shift; my $fh = IO::File->new; $fh->open($file, "r") or die $!; my $r = {}; # hashref return # erste Zeile mit den Überschriften einlesen my $headline = <$fh>; # weg damit # lese den Rest while(my $line = <$fh>){ my $namedef = Names->new( {0 => 'V1', 1 => 'V2', 2 => 'V3', 3 => 'V4', 4 => 'V5', 5 => 'V6'}, [split /\s+/, $line] ); $r->{$namedef->{V1}} = $namedef; } $fh->close; return $r; } # ein kleines Helferlein package Names; ########################################################################### # Rolf Rost, 14.2.2011 # Anonyme Array-Elemente bekommen Namen ########################################################################### use strict; # Setzt ein Array in ein Objekt um sub new{ my $class = shift; my $maps = shift; # {3 => 'Day', 4 => 'Month', 5 => 'Year'} my $aref = shift; # p.e. from localtime, stat, etc. return if ref $maps ne 'HASH'; return if ref $aref ne 'ARRAY'; my $self = {}; for(my $i = 0; $i < scalar(@$aref); $i++){ $self->{$maps->{$i}} = $aref->[$i] if exists $maps->{$i}; } return bless $self, $class; } 1; ########################################################################