• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

abgdf

Guru
andreasandy schrieb:
Außerdem, möchte ich jetzt versuchen das mit dem "SAT" und nicht benötigten Zeilen auch in Python zu lösen.
Mein "Perl-mit-Klassen"-Angebot war eigentlich eine Übersetzung aus Python. In Foren poste ich nicht mehr gern in Python, weil dann die Anfänger oft schreiben "Das läuft nicht", weil sie es nicht schaffen, den Code mit den Einrückungen richtig in ihren Editor einzufügen, und ich keinen Bock habe, das jedesmal zu erklären. Aber mein Python-Code sah eigentlich so aus:
Code:
#!/usr/bin/python
# coding: utf-8

class Line:

    def __init__(self, nr, first, second, third):
        self.nr = nr
        self.first = first
        self.second = second
        self.third = third
        self.output = True

    def check(self, nr_in, first_in, second_in):
        if self.nr == nr_in:
            return
        # print first_in, second_in
        if self.first == second_in and self.second == first_in: 
            self.output = False

    def checkandprint(self):
        if self.output:
            print str(self.nr) + ": " + self.second + ";" + self.first + ";" + self.third

def getData():
    a = """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"""
    return a.split("\n")

a = getData()
lines = []
n = 1
for i in a:
    b = i.split(";")
    lines.append(Line(n, b[0], b[1], b[2]))
    n += 1

for i in lines:
    for u in lines:
        i.check(u.nr, u.first, u.second)

for i in lines:
    i.checkandprint()
Ich halte das nach wie vor für am übersichtlichsten.
 
OP
A

andreasandy

Newbie
abgdf schrieb:
andreasandy schrieb:
Außerdem, möchte ich jetzt versuchen das mit dem "SAT" und nicht benötigten Zeilen auch in Python zu lösen.
Mein "Perl-mit-Klassen"-Angebot war eigentlich eine Übersetzung aus Python. In Foren poste ich nicht mehr gern in Python, weil dann die Anfänger oft schreiben "Das läuft nicht", weil sie es nicht schaffen, den Code mit den Einrückungen richtig in ihren Editor einzufügen, und ich keinen Bock habe, das jedesmal zu erklären. Aber mein Python-Code sah eigentlich so aus:
......
Ich halte das nach wie vor für am übersichtlichsten.

Vielen Dank! Ja, das mit den richtigen Einrückungen beim Python ist mir bekannt!
 

framp

Moderator
Teammitglied
abgdf schrieb:
...In Foren poste ich nicht mehr gern in Python, weil dann die Anfänger oft schreiben "Das läuft nicht", weil sie es nicht schaffen, den Code mit den Einrückungen richtig in ihren Editor einzufügen...
Das habe ich ja noch nie gehört dass jemand lesbaren Python Code in unlesbaren Perl Code transformiert damit ein Anfänger den Code besser versteht :schockiert: Ich denke Du scherzt.
 

abgdf

Guru
framp schrieb:
Das habe ich ja noch nie gehört dass jemand lesbaren Python Code in unlesbaren Perl Code transformiert damit ein Anfänger den Code besser versteht :schockiert: Ich denke Du scherzt.
Selbst wenn man Perl-Code nicht versteht, ist er beim Rüberkopieren mit den geschweiften Klammern ziemlich robust, das klappt meistens.

Wenn mein Perl-Code für Dich unlesbar, also unverständlich ist, hättest Du damit eine gute Gelegenheit, OOP in Perl kennenzulernen. Ich habe das wie gesagt auf meiner Seite beschrieben.
Es ist eigentlich ganz einfach, wenn man es (wie Du) in Python schon kennt. Statt
Code:
class SomeObject:

    def __init__(self):
        self.attr = 1

s = SomeObject()
print s.attr
schreibt man:
Code:
package SomeObject {

    sub new {
        my $classname = shift;
        my $self = {attr => 1};
        return bless($self, $classname);
    }
}
my $s = SomeObject->new();
print $s->{attr} . "\n";
Auf Attribute greift man danach also einfach mit "$obj->{attributename}" (Perl) zu statt mit "obj.attributename" (Python).
Auf Methoden mit "$obj->method()" (Perl) statt mit "obj.method()" (Python).

Das Tolle ist, man kann Perl-Objekte, die ja eine Vielzahl von Attributen und Methoden enthalten können, einfach als Ganzes an Funktionen übergeben, ohne groß über Dereferenzierungen nachdenken zu müssen.

Wie gehabt ist Perl-Code mit seinen Sigils und den Semikola am Zeilenende etwas weniger übersichtlich.
Daß bei OOP diese vielleicht etwas merkwürdige Syntax verwendet wird, liegt daran, daß OOP in Perl erstmals in Version 5 nachträglich eingefügt wurde, und viele Bezeichner wie z.B. der Punkt (".") vorher schon vergeben waren. Mit Hilfe dieser merkwürdigen Syntax mußte der Sprache selbst nur die Funktion "bless()" hinzugefügt werden, damit OOP möglich wurde.

Man muß auch sehen, daß "def __init__(self):" auf den ersten Blick auch nicht so leicht zu verstehen ist.
In beiden Fällen ist es einfach diese "Klassenmagie". Mit der man sich aber gar nicht groß zu beschäftigen braucht. Es ist einfach die Funktion, die aufgerufen wird, wenn ein Objekt instantiiert wird.

Ich gebe aber zu, wenn ich die Sprache für ein OOP-Programm wähle, greife ich meistens zu Python.
In Perl ist es alles ein wenig komplizierter, ohne daß es einen großen Vorteil bringen würde. Abgesehen vom Posten in Foren. ;)
 
OP
A

andreasandy

Newbie
Hallo alle zusammen!

Als erstes wünsche ich Euch ein frohes und gesundes Neues Jahr!

Und nun zu meinen Problemen :)
So, die Geschichte geht weiter, und zwar, so.

Hier ist noch Mal der Input:

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

Und jetzt soll der Output so aussehen:

"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"
"FAC";"AAA";"26"
"FAV";"AAA";"15"
"HOI";"AAA";"33"
"PPT";"AAA";"45"
"RRR";"AAA";"88"
"TTQ";"AAA";"87"

Also, dazu kommen noch doppelte Hochkommas. Das habe ich so gelöst:

Code:
BEGIN{
        OFS=";"
        FS=";"
};

{	if ($1 == "SAT")
	{
	x[$2,$3]=$4
	};
};

END{
	for (i in x) 
	{
           	split(i,y,SUBSEP);
           	print "\""y[1]"\"","\""y[2]"\"","\""x[i]"\""
           	if (!((y[2],y[1]) in x)) 
		{
               		print "\""y[2]"\"","\""y[1]"\"","\""x[i]"\""
		}
       	}	
}

So weit so gut, aber: leider hat das letzte Feld in den Zeilen Mal ein Leerzeichen, Mal mehrere, Mal keines. Und ich bekomme so einen Output:

"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 "
"FAC";"AAA";"26 "
"FAV";"AAA";"15 "
"HOI";"AAA";"33 "
"PPT";"AAA";"45"
"RRR";"AAA";"88 "
"TTQ";"AAA";"87 "

Die Leerzeichen müssen aber weg. Nun habe ich versucht das mit gsub zu lösen, z.B, so:

Code:
print "\""y[1]"\"","\""y[2]"\"","\""gsub(/ /,"")x[i]"\""

Das klappt aber nicht. Könnt Ihr mir bitte hier helfen?
 
A

Anonymous

Gast
andreasandy schrieb:
......
So weit so gut, aber: leider hat das letzte Feld in den Zeilen Mal ein Leerzeichen, Mal mehrere, Mal keines. Und ich bekomme so einen Output:
.......
Die Leerzeichen müssen aber weg. Nun habe ich versucht das mit gsub zu lösen, z.B, so:

Code:
print "\""y[1]"\"","\""y[2]"\"","\""gsub(/ /,"")x[i]"\""

Das klappt aber nicht. Könnt Ihr mir bitte hier helfen?

Die Aufgabenstellung war im Eröffnungsbeitrag umfassend beschrieben, das ist von uns umfassend gelöst und zwar mehrfach und auch noch in verschiedenen Scriptsprachen.

Wenn jetzt die dort uns zur Verfügung gestellten Daten und Aufgabenstellung nicht wirklich, korrekt und zutreffend sind, glaube ich im Namen vieler Helfer hier zu sprechen, ist das nicht mehr wirklich unser Bier.
Hilfeeinstieg für awk gibts im Wiki, deinen Fehler mit der gsub Funktion kannst du ganz schnell zB in einem der Anhänge im AWK-Betrag auf die auf die Spur kommen ,
nur nach gsub dort suchen und du wirst lesen: "Ersetzt r überall in t durch s ; gibt Anzahl Ersetzungen zurück, ohne t wird $0 verwendet [ global ]"
Und schon wirst du den Doppelfehler sehen, gsub ist nicht die richtige Funktion in diesem Kontex, da von dieser die Anzahl der Ersetzungen zurückgeliefert wird du aber hier das Ergebnis haben willst, und außerdem musst du hier explizied t angeben, da default-$0 hier absolut unpassend und in der END-Bedingung sowieso ohne explizites Einlesen so auch nicht wirklich brauchbar ist.
Warum willst du das denn überhaupt in der Ausgabe machen? dort müsste es auch noch 2 mal gemacht werden, Progammablauf genauer anschauen/durchdenken und gleich beim einsammeln der Daten ins Array die Leerzeichen entfernen.

robi
 

framp

Moderator
Teammitglied
robi schrieb:
... glaube ich im Namen vieler Helfer hier zu sprechen, ist das nicht mehr wirklich unser Bier.
Da bin ich mit Dir Robi.
Die Aufgabenstellung war im Eröffnungsbeitrag umfassend beschrieben, das ist von uns umfassend gelöst und zwar mehrfach und auch noch in verschiedenen Scriptsprachen.
Kleine Korrektur: Go gehört nicht zu den Scriptsprachen ;)
 
A

Anonymous

Gast
abgdf schrieb:
Ich hab' hier folgende Daten: asdasuqweqioadjkdhal
Und das soll zu: eqweqiwiaafciaoa
Und das bitte schön in Brainfuck."

Immer diese Sonderwünsche ;)

Der BF-Code in der Datei test.bf
Code:
robi@ULTRA-01:/tmp> cat test.bf
+[,]
++++[->++++++++<]>.+[->+++<]>++.++++++++++++.++++++.[->+++<]>.
++++++++++++.--------.-[--->+<]>-.+[->+++<]>+.
--------..+++++.---.++++++.--------.
++++++++++++++.--------------.>++++++++++.
einen BF-Interpreter brauchen wir auch, hier mal ein Beispiel als C-Quelltext bf.c
einfach mit gcc kompilieren.
Code:
robi@ULTRA-01:/tmp> cat bf.c
#include<stdio.h>  // Krzysztof Gabis 2015
#include<stdlib.h> // Usage: ./bf program
int p[64*1024],d[1024*1024],r,c,t,e;int main(int c,char*v[]){
if(c<2)exit(1);FILE*f=fopen(v[1],"r");while(f&&(c=getc(f))!=
EOF)p[r++]=c;r=0;while((c=p[r])){e=0;if(c=='>')t++;if(c=='<')
t--;if(c=='+')d[t]++;if(c=='-')d[t]--;if(c=='.')putc(d[t],
stdout);if(c==',')d[t]=getc(stdin);while(c=='['&&!d[t]){if(
p[r]=='[')e++;if(p[r]==']'&&e--==1)break;r++;}while(c==']'&&
d[t]){if(p[r]==']')e++;if(p[r]=='['&&e--==1)break;r--;}r++;}}

robi@ULTRA-01:/tmp> gcc -o bf bf.c

dann nur noch ausführen, der einfachheitshalber habe ich die Eingabe mal NULL-Terminiert.
Code:
robi@ULTRA-01:/tmp> echo -e "asdasuqweqioadjkdhal\0" | ./bf test.bf
 eqweqiwiaafciaoa
Nur zum Spaß hat der BF-Quelltext noch ein besonderes Feature, jede andere NULL-Terminierte Eingabe ergibt genau das selbe Ergebnis ;)
für mehr hat meine Lust heute dafür nicht mehr ausgereicht.

robi
 

gehrke

Administrator
Teammitglied
Das kommt davon, wenn man hier zu lange abhängt. Muss schnellstmöglich den Absprung finden und irgendwas mit Holz machen...
 

uhelp

Member
Code:
sed -ir '/^PVO/d;/^POU/d;/^ODT/d;' /Pfad/zu/deinem/DeinDatenFile  |
awk -F';' 'BEGIN{ i=0
     }
     { array[i++]="\" $1 "\";\"" $2 "\";\"" $3 "\"
       array[i++]="\" $2 "\";\"" $1 "\";\"" $3 "\"
     }
     END{ for (element in array)
         print array[element]
     }
     ' | sort -u
Beachte, dass das alles eine einzige Zeile ist.
Dem Pipezeichen am Ende der ersten Zeile darf KEIN weiteres Zeichen folgen.
 
Oben