Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

abgdf
Guru
Guru
Beiträge: 3109
Registriert: 13. Apr 2004, 21:15

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von abgdf » 28. Dez 2017, 20:18

andreasandy hat geschrieben:
28. Dez 2017, 19:12
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: Alles auswählen

#!/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.

Werbung:
andreasandy
Newbie
Newbie
Beiträge: 13
Registriert: 25. Dez 2017, 00:06

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von andreasandy » 28. Dez 2017, 20:53

framp hat geschrieben:
28. Dez 2017, 19:21
andreasandy hat geschrieben:
28. Dez 2017, 18:48
Ich habe nur vor ein Paar Tagen zum ersten Mal etwas über Go gehört. Steht nicht ganz oben auf meiner Prio-Liste...
Wenn Du an einem Job bei Google interessiert bist solltest Du Deine Prioritäten vielleicht ändern :wink:
Was ist Google?

andreasandy
Newbie
Newbie
Beiträge: 13
Registriert: 25. Dez 2017, 00:06

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von andreasandy » 28. Dez 2017, 20:56

abgdf hat geschrieben:
28. Dez 2017, 20:18
andreasandy hat geschrieben:
28. Dez 2017, 19:12
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!

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4270
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von framp » 28. Dez 2017, 21:24

andreasandy hat geschrieben:
28. Dez 2017, 20:53
Was ist Google?
:-D Ein bei jungen Leuten sehr begehrter Arbeitgeber. Demnach gehörst Du nicht zu denen :lol:

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4270
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von framp » 28. Dez 2017, 21:27

abgdf hat geschrieben:
28. Dez 2017, 20:18
...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.

josef-wien
Ultimate Guru
Ultimate Guru
Beiträge: 5099
Registriert: 23. Sep 2008, 17:09

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von josef-wien » 28. Dez 2017, 22:00

andreasandy hat geschrieben:
28. Dez 2017, 19:12
warum keine abschließende geschweifte Klammer zu diesem Ausdruck erforderlich ist
Sie ist vorhanden, nämlich drei Zeilen später:

Code: Alles auswählen

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

abgdf
Guru
Guru
Beiträge: 3109
Registriert: 13. Apr 2004, 21:15

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von abgdf » 28. Dez 2017, 22:09

framp hat geschrieben:
28. Dez 2017, 21:27
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: Alles auswählen

class SomeObject:

    def __init__(self):
        self.attr = 1

s = SomeObject()
print s.attr
schreibt man:

Code: Alles auswählen

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. ;)

andreasandy
Newbie
Newbie
Beiträge: 13
Registriert: 25. Dez 2017, 00:06

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von andreasandy » 28. Dez 2017, 22:24

josef-wien hat geschrieben:
28. Dez 2017, 22:00
andreasandy hat geschrieben:
28. Dez 2017, 19:12
warum keine abschließende geschweifte Klammer zu diesem Ausdruck erforderlich ist
Sie ist vorhanden, nämlich drei Zeilen später:

Code: Alles auswählen

{	if ($1 == "SAT")
{
	x[$2,$3]=$4};
};
Stimmt :-) Jetzt sehe ich sie. Vielen Dank, josef-wien!

andreasandy
Newbie
Newbie
Beiträge: 13
Registriert: 25. Dez 2017, 00:06

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von andreasandy » 3. Jan 2018, 14:27

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: Alles auswählen

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: Alles auswählen

print "\""y[1]"\"","\""y[2]"\"","\""gsub(/ /,"")x[i]"\""
Das klappt aber nicht. Könnt Ihr mir bitte hier helfen?

abgdf
Guru
Guru
Beiträge: 3109
Registriert: 13. Apr 2004, 21:15

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von abgdf » 3. Jan 2018, 16:25

"Hallo alle zusammen!
Ich hab' hier folgende Daten: asdasuqweqioadjkdhal
Und das soll zu: eqweqiwiaafciaoa
Und das bitte schön in Brainfuck."
Glaubst Du da hat jemand Lust zu?

andreasandy
Newbie
Newbie
Beiträge: 13
Registriert: 25. Dez 2017, 00:06

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von andreasandy » 3. Jan 2018, 17:12

abgdf hat geschrieben:
3. Jan 2018, 16:25
"Hallo alle zusammen!
Ich hab' hier folgende Daten: asdasuqweqioadjkdhal
Und das soll zu: eqweqiwiaafciaoa
Und das bitte schön in Brainfuck."
Glaubst Du da hat jemand Lust zu?
Ja.

Benutzeravatar
gehrke
Moderator
Moderator
Beiträge: 1840
Registriert: 10. Nov 2012, 11:00
Wohnort: Münsterland

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von gehrke » 3. Jan 2018, 17:36

@andreasandy: Bitte keine unangebrachten Full Quotings.
TNX

Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3160
Registriert: 25. Aug 2004, 02:13

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von robi » 3. Jan 2018, 20:55

andreasandy hat geschrieben:
3. Jan 2018, 14:27
......
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: Alles auswählen

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

Benutzeravatar
framp
Moderator
Moderator
Beiträge: 4270
Registriert: 6. Jun 2004, 20:57
Wohnort: bei Stuttgart
Kontaktdaten:

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von framp » 3. Jan 2018, 21:40

robi hat geschrieben:
3. Jan 2018, 20:55
... 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 ;)

Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3160
Registriert: 25. Aug 2004, 02:13

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von robi » 4. Jan 2018, 00:18

abgdf hat geschrieben:
3. Jan 2018, 16:25
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: Alles auswählen

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: Alles auswählen

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: Alles auswählen

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

Benutzeravatar
gehrke
Moderator
Moderator
Beiträge: 1840
Registriert: 10. Nov 2012, 11:00
Wohnort: Münsterland

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von gehrke » 4. Jan 2018, 01:16

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

abgdf
Guru
Guru
Beiträge: 3109
Registriert: 13. Apr 2004, 21:15

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von abgdf » 4. Jan 2018, 02:55

robi hat geschrieben:
4. Jan 2018, 00:18
Immer diese Sonderwünsche ;)

Der BF-Code in der Datei test.bf
:schockiert:

:thumbs:

uhelp
Member
Member
Beiträge: 105
Registriert: 25. Nov 2012, 19:33

Re: Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Beitrag von uhelp » 7. Mai 2018, 22:31

Code: Alles auswählen

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.

Antworten