Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

andreasandy

Newbie
Registriert
Dez. 2017
Beiträge
3
Hallo alle zusammen!

Bei folgender Aufgabe komme ich nicht weiter.
Hier ist der zu verarbeitende Inhalt einer Datei (die Zeilennummern gehören nicht zum Inhalt, nur für die nachfolgende Erläuterung der Aufgabenstellung) :

01. AAA;AAB;10
02. AAB;AAA;12
03. AAA;FAC;26
04. AAA;FAV;15
05. DAD;HHZ;89
06. AAA;HOI;33
07. AAA;MKP;59
08. AAA;PPT;45
09. AAA;RRR;88
10. AAA;TTQ;87
11. HHZ;DAD;89
12. MKP;AAA;59

Diese Datei muss eingelesen werden, ausgegeben müssen alle vorhandenen Zeilen und die Zeilen, wo $1 der Zeile n nicht gleich $2 der Zeile m ist und $2 der Zeile n nicht gleich $1 der Zeile m ist, und in dieser Reihenfolge: $2;$1;$3.

Also, Zeile 1 und Zeile 2 müssen nicht angefasst werden, weil da findet man in beiden Zeilen Werte AAA und AAB, nur verdreht. Genauso Zeile 5 und Zeile 11, und Zeile 7 und Zeile 12.
Alle anderen Zeilen haben sozusagen, keine gespiegelten "Doppelgänger" und für Sie muss so ein "Doppelgänger" generiert und der Datei hinzugefügt werden (an welcher Stelle, spielt keine Rolle).

Das ist der gewünschte Output:

01. AAA;AAB;10
02. AAB;AAA;12
03. AAA;FAC;26
04. AAA;FAV;15
05. DAD;HHZ;89
06. AAA;HOI;33
07. AAA;MKP;59
08. AAA;PPT;45
09. AAA;RRR;88
10. AAA;TTQ;87
11. HHZ;DAD;89
12. MKP;AAA;59
13. FAC;AAA;26
14. FAV;AAA;15
15. HOI;AAA;33
16. PPT;AAA;45
17. RRR;AAA;88
18. TTQ;AAA;87

Könnte mir bitte jemand helfen? Alle meine Versuche bleiben bisher erfolglos. Muss auch nicht unbedingt mit AWK erledigt werden. Danke!
 
Hallo andreasandy,

meine Lösung ist in Perl:

Folgende Zeilen als "twins.pl" speichern:
Code:
#!/usr/bin/perl -w


my %twins= ();

while(my $line=<>)
{
  chomp $line;
  my @p= split(";", $line);
  print $line,"\n";
  $twins{ $p[0] . ";" . $p[1] }= $p[2];
}

foreach my $k (keys %twins)
{
  my @p= split(";", $k);
  if (!exists($twins{ $p[1] . ";" . $p[0] }))
  {
    printf("%s;%s;%s\n", $p[1], $p[0], $twins{ $p[0] . ";" . $p[1] });
  }
}

Mit der Datei
Code:
AAA;AAB;10
AAB;AAA;12
AAA;FAC;26
AAA;FAV;15
DAD;HHZ;89
AAA;HOI;33
AAA;MKP;59
AAA;PPT;45
AAA;RRR;88
AAA;TTQ;87
HHZ;DAD;89
MKP;AAA;59
als "twins_in.txt"

liefert ein

Code:
perl twins.pl <twins_in.txt

die Ausgabe
Code:
AAA;AAB;10
AAB;AAA;12
AAA;FAC;26
AAA;FAV;15
DAD;HHZ;89
AAA;HOI;33
AAA;MKP;59
AAA;PPT;45
AAA;RRR;88
AAA;TTQ;87
HHZ;DAD;89
MKP;AAA;59
HOI;AAA;33
TTQ;AAA;87
RRR;AAA;88
PPT;AAA;45
FAC;AAA;26
FAV;AAA;15


HTH

BigNum
 
Hallo BigNum, vielen Dank für Deine Lösung! Ich werde mir das anschauen. Habe vor Jahren angefangen Perl zu lernen, dann aber zu Python übergegangen.
 
Da auf 98% der Systeme, auf denen awk läuft auch Perl läuft war es für mich naheliegend das Ganze in Perl zu coden.
Aber selbstverständlich kann man das auch in Python machen:

twins.py
Code:
import sys


twins= {}
for line in sys.stdin:
    l= line.rstrip('\n\r')
    print l
    p= l.split(";")
    twins[ p[0] + ';' + p[1] ]= p[2]

for k in twins.keys():
    p= k.split(";")
    if (twins.get(p[1] + ';' + p[0]) == None):
        print p[1] + ';' + p[0] + ';' + twins[k]

liefert mit derselben "twins_in.txt" wie oben (Beitrag #2) nach einem Aufruf mittels

Code:
python2.7 twins.py < twins_in.txt

die Ausgabe

Code:
AAA;AAB;10
AAB;AAA;12
AAA;FAC;26
AAA;FAV;15
DAD;HHZ;89
AAA;HOI;33
AAA;MKP;59
AAA;PPT;45
AAA;RRR;88
AAA;TTQ;87
HHZ;DAD;89
MKP;AAA;59
PPT;AAA;45
FAC;AAA;26
HOI;AAA;33
RRR;AAA;88
TTQ;AAA;87
FAV;AAA;15

Du kannst Dir ja mal sozusagen als Zusatzaufgabe überlegen, warum die beiden Ausgaben nicht identisch sind ;)


HTH

BigNum
 
Hallo BigNum, danke auch für die Lösung mit Python! Ich werde das testen und Deine "Zusatzaufgabe" bearbeiten ;-)
Zumal hat das Input-File in Wirklichkeit so eine Form:

PVO;20170301
POU;20170531
SAT;AAA;AAB;10
SAT;AAB;AAA;12
SAT;AAA;FAC;26
SAT;AAA;FAV;15
SAT;DAD;HHZ;89
SAT;AAA;HOI;33
SAT;AAA;MKP;59
SAT;AAA;PPT;45
SAT;AAA;RRR;88
SAT;AAA;TTQ;87
SAT;HHZ;DAD;89
SAT;MKP;AAA;59
ODT;508

Das heißt, es müssen noch immer die ersten 2 Zeilen und die letzte entfernt werden, und bei den nützlichen Zeilen das "SAT;" entfernt werden (das "SAT" steht da immer vor diesen Zeilen).

Aber lass mich bitte selbst versuchen das zu lösen :-)

Grüße,
andreasandy
 
Zurück
Oben