Grep nach zwei Parametern und in eine CSV-Datei...

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
desputin
Beiträge: 1349
Registriert: 24.04.2015 17:16:34

Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von desputin » 02.07.2020 15:56:23

Hallo Ihr,

ich habe html-Dateien, in denen viele E-Mail-Adressen drin sind.
Nun möchte ich zum einen einen Nummer aus sehr vielen html-Dateien und zum anderen eine E-Mail-Adresse rausfiltern und die in eine csv-Datei jeweils in eine Zeile tun pro E-Mail-Adresse und Nummer.
Die E-Mail-Adresse würde ich so rausziehen:

Code: Alles auswählen

grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b"
Und die Nummer sieht so aus:

Code: Alles auswählen

"MaStR-Nummer">SNB976089191796</td>

bzw. so:

Code: Alles auswählen

"MaStR-Nummer">SNB944835186174</td>
1. Wie würdet Ihr also die MaStR-Nummer rausziehen (nur die Nummer selber, die mit SNB... anfängt)
2. Wie würdet Ihr dann jeweils die gegrepte E-Mail-Adresse und die MaStR-Nummer zusammen in die CSV-Datei kopieren?

Viele Grüße
desputin
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 02.07.2020 16:09:56

Wie sehen die Ausgangsdaten aus? Bitte poste einen (anonymisierten) Ausschnitt.

Woher weiss man welche Email-Adresse zu welcher Nummer gehoert?
Use ed once in a while!

Benutzeravatar
desputin
Beiträge: 1349
Registriert: 24.04.2015 17:16:34

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von desputin » 02.07.2020 16:37:25

Die Ausgagnsdateien sind einfache über curl heruntergeladene html-Dateien. Die entsprechenden Passagen sehen so aus:

Code: Alles auswählen

<tr class="detailstammdaten email"><td class="display-template-label" title=""></td><td class="display-template-value " title="">info@xyz.eu</td><td class="js-form-helper-panel-detail"><i class="icon-form-helper far fa-info-circle text-primary" data-hilfetext="Öffentliche E-Mail-Adresse"></i></td></tr>
bzw.

Code: Alles auswählen

<tr class=""><td class="display-template-label" title="MaStR-Nummer der Marktrolle">MaStR-Nummer der Marktrolle:</td><td class="display-template-value " title="MaStR-Nummer der Marktrolle">SNB000835186174AN</td><td class="js-form-helper-panel-detail">
Man weiß, daß E-Mail und Nummer jeweils zusammengehören, weil pro html-Datei immer nur eine E-Mail und eine Nummer enthalten sind.
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

cronoik
Beiträge: 2049
Registriert: 18.03.2012 21:13:42
Lizenz eigener Beiträge: GNU Free Documentation License

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von cronoik » 02.07.2020 17:44:36

desputin hat geschrieben: ↑ zum Beitrag ↑
02.07.2020 15:56:23
1. Wie würdet Ihr also die MaStR-Nummer rausziehen (nur die Nummer selber, die mit SNB... anfängt)
Dafuer lieferst du zu wenig Informationen. Gibt es aehnliche Nummern, sind die MaStR Nummer immer gleich lang, ist es immer SNBZAHLEN (Nein? -> [1]), wIllst du nur die Zahlen?

Wenn ich allerdings deine html Schnippsel sehe, dann wuerde ich es gleich ueber XPath oder ueber css selector matchen.

[1] https://www.bundesnetzagentur.de/Shared ... onFile&v=2
Hilf mit unser Wiki zu verbessern!

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 02.07.2020 18:25:14

Code: Alles auswählen

awk -F"[<>]" '/MaStR/{for (i=NF; i>0; i--){ if (substr($i,0,3)=="SNB") nummer = substr($i,4) }}  /tr class="detailstammdaten email"/{ for (i=NF; i>0; i--){  if (index($i,"@") != 0) { print $i; email =  $i } }}    END{print nummer " : " email}' daten.txt
Ob das so reicht? Keine Ahnung, kann man bei nur einer Zeile Daten nicht sagen.
Was passiert?
-F setzt den Feldtrenner auf "<" und ">", also dazwischen entstehen einzelne Felder
/MaStR/ sagt, tu mal das folgende, falls die Zeile MaStR enthält, analog der zweite Block falls der andere Teil drin ist - das ist vermutlich die Stelle an der Du gegebenfalls nacharbeiten musst
substr gibt nen Teil des Strings, hier schauen wir ob der String mit SNB anfängt und geben den Rest aus, willst Du die ganze Nr . incl dem SNR, dann eben entsprechend anpassen
index gibt die Fundstelle eines Zeichens, gehen wir mal davon aus, dass "@" wirklich nur in der Email vorkommt

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 02.07.2020 20:13:47

Den Befehl von eggy habe ich nicht genauer angeschaut. Ich wuerde so ansetzen:

Code: Alles auswählen

egrep -Ho 'EMAILRE|NUMMERRE' | awk '...' DATEIEN...
Egrep erzeugt pro Datei jeweils zwei Zeilen, die beide mit dem Dateiname starten und dahinter entweder die Mailadresse oder die Nummer haben. Diese Paare wuerde ich mit awk in zwei Arrays einlesen, etwa in der Art:

Code: Alles auswählen

$2 ~ /@/ { email[$1] = $2 }
$2 !~ /@/ { nummer[$1] = $2 }
Dann im END-Block ueber die Arrays iterieren und passend ausgeben.


Alternativ mit sed (und weniger robust, aber dafuer kuerzer):

Code: Alles auswählen

egrep -ho 'EMAILRE|NUMMERRE' | sed 'N;s,\n,;,p'
(alles ungetestet)
Use ed once in a while!

Benutzeravatar
desputin
Beiträge: 1349
Registriert: 24.04.2015 17:16:34

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von desputin » 03.07.2020 12:40:20

Hallo Ihr,
vielen Dank für Eure Vorschläge!

Den Befehl von eggy habe ich gerade getestet und er funktioniert soweit. Der Output sieht jetzt z.B. so aus:

Code: Alles auswählen

mail@mail.de
913131154136BV : mail@mail.de
Zwei kleine Dinge Verbesserungsfragen hätte ich noch:
  • Wie kann ich das BV am Ende der Nummer wegbekommen?
  • Die E-Mail-Adresse steht da jetzt zwei Mal, ich brauche nur eine davon...
  • Wie kann ich dann aus vielen html-Dateien eine CSV-Liste machen? Ich nehme an, irgendwie so:
Statt daten.txt am Ende sowas wie *.*html für alle html-Dateien in dem Ordner. und dann > Output-Liste.csv.
Aber wie bekomm ich das dann in einer CSV-Ordnung mit zwei Spalten Nummer und E-Mail?
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 03.07.2020 13:32:29

  • Wie kann ich das BV am Ende der Nummer wegbekommen?
gibt mehrere Ansätze, hängt davon ab, wie die Struktur der Nr ist, je nachdem: man könnt's über die Länge des Strings lösen oder einfach alle Buchstaben per regex und gsub rauswerfen, scheint hier einfacher
  • Die E-Mail-Adresse steht da jetzt zwei Mal, ich brauche nur eine davon...
ganz einfach: den print Befehl rausnehmen
  • Wie kann ich dann aus vielen html-Dateien eine CSV-Liste machen? Ich nehme an, irgendwie so: ...
fast, Problem wenn man END benutzt, die Ausgabe erscheint erst am Ende des gesamten Durchlaufs, d.h. die von uns genutzen Variablen werden zwischendurch überschrieben.
Meillo hat schon eine Lösung mitgeliefert: man nimmt ein Array und speichert darin seine Ergebnisse zwischen, oder was ich oftmals netter finde: man nutzt ENDFILE, der Block wird immer dann abgearbeitet, wenn awk eine Eingabedatei durch hat
  • Aber wie bekomm ich das dann in einer CSV-Ordnung mit zwei Spalten Nummer und E-Mail?
tausch den Doppelpunkt im END-Block gegen nen Semikolon

Code: Alles auswählen

awk -F"[<>]" '/MaStR/{for (i=NF; i>0; i--){ if (substr($i,0,3)=="SNB") { gsub("[^0-9]","",$i); nummer=$i} }}  /tr class="detailstammdaten email"/{ for (i=NF; i>0; i--){  if (index($i,"@") != 0) { email =  $i } }}    ENDFILE{print nummer ";" email}' *.html
Beim nächsten mal erstmal selbst rum probieren und Deinen (auch Fehl-) Versuch posten. Dann kann man zeigen, wo es verbessert werden kann. awk ist ne echt schöne Sprache für solche Aufgaben, da lohnt sich das reinarbeiten. Und wenn man mal auf den Holzweg abbiegt, gibts hier sicher jemanden, der den Rückweg zeigen kann. Nur probieren musst selbst, vom andere-machen-lassen wirst Du das nicht lernen. Wär schade drum.

Benutzeravatar
desputin
Beiträge: 1349
Registriert: 24.04.2015 17:16:34

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von desputin » 03.07.2020 13:52:01

Hallo Eggy, Ihr,

wunderbar!! So hat es nun 1a geklappt:

Code: Alles auswählen

 awk -F"[<>]" '/MaStR/{for (i=NF; i>0; i--){ if (substr($i,0,3)=="SNB") { gsub("[^0-9]","",$i); nummer=$i} }}  /tr class="detailstammdaten email"/{ for (i=NF; i>0; i--){  if (index($i,"@") != 0) { email =  $i } }}    ENDFILE{print nummer ";" email}' *.*html > output.csv
Nächstes Mal hangle ich mich einfach durch den Befehl durch. Meistens kann ich solche Befehle führ mehrere Zwecke "recyclen".... Danke!
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 03.07.2020 14:15:42

@eggy: Deine Variante geht nur in GNU awk. Mawk kennt kein `ENDFILE'. Das koennte man mit `END' und einer Shell-Schleife loesen. Zudem tut irgendwas in dem Nummer-Code nicht, aber ich habe noch nicht rausgefunden was.


Hier zur Ergaenzung noch meine Umsetzung, die ich nun lauffaehig gemacht habe:

Code: Alles auswählen

egrep -ho '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}|SNB[0-9]+' "$@" | sed 'N;s,\n,;,;s,SNB,,'
(Wenn man den Befehl ohne umgebendes Shellscript ausfuehrt, muss man "$@" durch *.html ersetzen.)
Use ed once in a while!

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 03.07.2020 14:24:19

@Meillo: ich hab hier auf den Kisten immer gawk, der einzige Fall wo ich mal gawk hatte, war irgendnen komisches awk auf nem Solaris und da konnte man sich nicht drauf verlassen, dass die Arrays sortiert waren, das war nen "Spass". nie wieder. ... und eh ich mich nochmal damit rumärger, kompilier ich mir nen gawk selbst. Aber Danke für den Hinweis, ich achte generell viel zu wenig auf "läuft überall".

Was meinst Du mit "Nummern Code"?

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 03.07.2020 15:56:25

eggy hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 14:24:19
@Meillo: ich hab hier auf den Kisten immer gawk, der einzige Fall wo ich mal gawk hatte, war irgendnen komisches awk auf nem Solaris und da konnte man sich nicht drauf verlassen, dass die Arrays sortiert waren, das war nen "Spass". nie wieder. ... und eh ich mich nochmal damit rumärger, kompilier ich mir nen gawk selbst. Aber Danke für den Hinweis, ich achte generell viel zu wenig auf "läuft überall".
Von mir koennte man wohl das Gegenteil behaupten: Ich interessiere mich zu viel fuer die Unterschiede und zu wenig dafuer, dass es einfach laeuft. ;-) Darum habe ich auch bewusst einen mawk auf einem System. Und einen nawk habe ich auch ... und sogar einen oawk (aus den Heirloom-Tools) aber der ist echt 'ne andere Welt: Keine Funktionen und so!
Was meinst Du mit "Nummern Code"?
Bei mir ist die Ausgabe:

Code: Alles auswählen

;info@xyz.eu
Er findet also die Nummer nicht. Bisher habe ich noch nicht gedebuggt.
Use ed once in a while!

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 03.07.2020 16:40:30

mawk mit array ... igitt :mrgreen:

Code: Alles auswählen

mawk -F"[<>]" 'BEGIN {z=0; email[z]="email"; nummer[z]="nummer"; oldfile=""}  {if (FILENAME!=oldfile) {z=z+1; oldfile=FILENAME}}    /MaStR/{ for (i=NF; i>0; i--){ if (substr($i,0,3)=="SNB") { gsub("[^0-9]","",$i); nummer[z]=$i} }}  /tr class="detailstammdaten email"/{ for (i=NF; i>0; i--){  if (index($i,"@") != 0) { email[z] =  $i } }}    END{for ( i = 0; i <= z; i++) {print  nummer[i] ";" email[i] } }' *.html

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 03.07.2020 17:01:13

@desputin:
Awk kann man als "Einzeiler" oder mit script Datei nutzen.
Das gleiche wie oben nochmal in lesbar, so wird vielleicht besser klar, was da passiert

Code: Alles auswählen

BEGIN {
                FS = "[<>]" ;
                z=0; 
                email[z]="email";
                nummer[z]="nummer"; 
                oldfile=""
}  


{
                if (FILENAME!=oldfile) {
                                z=z+1; 
                                oldfile=FILENAME
                }
}


/MaStR/{ 
                for (i=NF; i>0; i--){ 
                                if (substr($i,0,3)=="SNB") { 
                                                gsub("[^0-9]","",$i); 
                                                nummer[z]=$i
                                } 
                }
}  

/tr class="detailstammdaten email"/{ 
                for (i=NF; i>0; i--){ 
                                if (index($i,"@") != 0) {
                                                email[z] =  $i 
                                }
                }
}

END{
                for ( i = 0; i <= z; i++) {
                                print  nummer[i] ";" email[i] 
                } 
}

awk -f script.awk *.html

Merkwürdigkeit am Rande: das ";" am Zeilenende ist nur nötig, wenn ein weiterer Befehl folgt.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 03.07.2020 19:20:32

eggy hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 16:40:30
mawk mit array ... igitt :mrgreen:

Code: Alles auswählen

mawk -F"[<>]" 'BEGIN {z=0; email[z]="email"; nummer[z]="nummer"; oldfile=""}  {if (FILENAME!=oldfile) {z=z+1; oldfile=FILENAME}}    /MaStR/{ for (i=NF; i>0; i--){ if (substr($i,0,3)=="SNB") { gsub("[^0-9]","",$i); nummer[z]=$i} }}  /tr class="detailstammdaten email"/{ for (i=NF; i>0; i--){  if (index($i,"@") != 0) { email[z] =  $i } }}    END{for ( i = 0; i <= z; i++) {print  nummer[i] ";" email[i] } }' *.html
In meinem mawk 1.3.3 geht der Code auch nicht. Ich habe nun aber den Fehler gefunden:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html#tag_20_06_13_13 hat geschrieben: substr(s, m[, n ])
Return the at most n-character substring of s that begins at position m, numbering from 1. If n is omitted, or if n specifies more characters than are left in the string, the length of the substring shall be limited by the length of the string s.
Du hast bei substr() mit 0 indiziert. ;-)

Gawk (und evtl. neuere mawk, falls du den Code mit mawk getestet hast) machen scheinbar automatisch eine Verschiebung, falls jemand substr() mit den zweiten Argument gleich 0 aufruft.

eggy hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 17:01:13
Merkwürdigkeit am Rande: das ";" am Zeilenende ist nur nötig, wenn ein weiterer Befehl folgt.
In der gelayouteten Version sind die Strichpunkte am Zeilenende unnoetig. Zeilenende und Strichpunkt bedeuten das gleiche. Man braucht den Strichpunkt nur wenn man auf der gleichen Zeile mehrere Kommandos haben will.

Das unterscheidet sich zu C, wo der Strichpunkt ein Statement-Terminator ist. Es unterscheidet sich aber auch zu Pascal, wo der Strichpunkt ein Statement-Trenner ist. In C geht nur das:

Code: Alles auswählen

{
	printf("hello ");
	printf("world!");
}
In Pascal geht nur das (in uebertragener Syntax):

Code: Alles auswählen

{
	printf("hello ");
	printf("world!")
}
In awk geht beides ... und zudem das:

Code: Alles auswählen

{
	printf("hello ")
	printf("world!")
}
Use ed once in a while!

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 03.07.2020 20:17:15

Ah danke, wieder was interessantes gelernt :THX:

In der gawk manpage steht übrigens
substr(s, i [, n]) Return the at most n-character substring of s starting at i. If n is omitted, use the rest of s.
Das mit den ";" war bekannt, ich hab nur nicht komplett auf dem Schirm gehabt, Muskelgedächnisautomatismen. Die Aussage war erstmal auf den Einzeilermodus bezogen und dann bin ich beim Umformatieren irgendwie davon abgekommen das zu Ende zu denken :oops:

tobo
Beiträge: 2349
Registriert: 10.12.2008 10:51:41

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von tobo » 03.07.2020 20:33:33

Meillo hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 19:20:32
In Pascal geht nur das (in uebertragener Syntax):
In Pascal funktionieren beide obere Versionen und im Normalfall würde man - wegen der Konsitenz - wohl auch die C-Version wählen (auch die letzte Zeile vor einem end-Statement gestrichpunktet). Es ist lediglich eine Option, das letzte Semikolon wegzulassen.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 03.07.2020 20:55:11

eggy hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 20:17:15
In der gawk manpage steht übrigens
substr(s, i [, n]) Return the at most n-character substring of s starting at i. If n is omitted, use the rest of s.
Die mawk Manpage ist leider auch nicht genauer, dabei waere es hier wirklich angebracht, da das eine fast offensichtliche Frage ist.

In PHP und Python sind Substrings zero-based.

In der Bash (grossteils ;-) ) auch:
Manpage bash(1) hat geschrieben: ${parameter:offset:length}
Substring Expansion. Expands to up to length characters of parameter
starting at the character specified by offset. [...]
Substring indexing is zero-based unless the positional
parameters are used, in which case the indexing starts at 1 by
default. If offset is 0, and the positional parameters are used, $0
is prefixed to the list.
Da hier awk aus der Reihe faellt, waere es gut, diese Abweichung zu thematisieren. (Das muss man aus heutiger Nutzungssicht sehen. Natuerlich ist awk aelter als diese Beispiele, aber heutige awk-Programmierer sind dennoch von ihnen gepraegt.)


Ich vermute, dass das bei awk so ist, weil awk auch zur direkten Nutzung durch Nichtprogrammierer vorgesehen war. Darum ist es so einfach und darum wohl auch die fuer Nichtprogrammierer natuerlichere Indizierung ab 1. Dennoch denke ich, dass das eine schlechte Designentscheidung war.

Es ist doch so: Wenn irgendwo ``index'' dran steht, dann fragt man sich *immer* sofort, ob ab 0 oder ab 1 gezaehlt wird. Aus diesem Grund sollte man den Begriff ``index'' vermeiden -- er ist nie klar. Im Gegensatz dazu der Begriff ``offset''. Dieser hat eine klare Semantik: Ein Offset von 0 ist der normale Start. Die Zahl gibt an wie viele Elemente uebersprungen werden. Dadurch wird unerheblich ob ab 0 oder ab 1 gezaehlt wird.

... ein kleiner Unterschied in der Namensgebung und im Design, ein grosser Unterschied in der Auswirkung!
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 03.07.2020 21:12:13

tobo hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 20:33:33
Meillo hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 19:20:32
In Pascal geht nur das (in uebertragener Syntax):
In Pascal funktionieren beide obere Versionen und im Normalfall würde man - wegen der Konsitenz - wohl auch die C-Version wählen (auch die letzte Zeile vor einem end-Statement gestrichpunktet). Es ist lediglich eine Option, das letzte Semikolon wegzulassen.
Du hast recht, da es ein Block ist, der eine statement-sequence enthaelt, kann ich nach dem letzten statement-separator (;) noch ein leeres Statement haben. Das geht bei statement-sequences, nicht aber bei simple-statements.

(Siehe auch: https://wiki.freepascal.org/;)
Use ed once in a while!

eggy
Beiträge: 3334
Registriert: 10.05.2008 11:23:50

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von eggy » 03.07.2020 21:16:40

https://www.gnu.org/software/gawk/manua ... -Functions
Similarly, index() works with character indices, and not byte indices.

CAUTION: A number of functions deal with indices into strings. For these functions, the first character of a string is at position (index) one. This is different from C and the languages descended from it, where the first character is at position zero. You need to remember this when doing index calculations, particularly if you are used to C.

tobo
Beiträge: 2349
Registriert: 10.12.2008 10:51:41

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von tobo » 04.07.2020 00:08:43

Meillo hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 21:12:13
Das geht bei statement-sequences, nicht aber bei simple-statements.

(Siehe auch: https://wiki.freepascal.org/;)
Ich weiß nicht genau, was du mit simple-statement meinst, aber dieses freepascal-Beispiel ist jedenfalls schwer hinkonstruiert: Strichpunkt vor else - beim if - ist nicht erlaubt, Strichpunkt vor else - bei einem case - ist notwendig. Der Strichpunkt aus dem Beispiel macht aus dem if-else ein case-else. Das ist zwar tatsächlich eine Demonstration, dass es auf jeden Strichpunkt ankommt, lässt sich aber auch an keinem anderen Beispiel, als diesem Beispiel, demonstrieren!? Spezialfälle taugen nichts für Regeln...

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von Meillo » 04.07.2020 08:51:32

tobo hat geschrieben: ↑ zum Beitrag ↑
04.07.2020 00:08:43
Meillo hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 21:12:13
Das geht bei statement-sequences, nicht aber bei simple-statements.

(Siehe auch: https://wiki.freepascal.org/;)
Ich weiß nicht genau, was du mit simple-statement meinst, aber dieses freepascal-Beispiel ist jedenfalls schwer hinkonstruiert: Strichpunkt vor else - beim if - ist nicht erlaubt, Strichpunkt vor else - bei einem case - ist notwendig. Der Strichpunkt aus dem Beispiel macht aus dem if-else ein case-else. Das ist zwar tatsächlich eine Demonstration, dass es auf jeden Strichpunkt ankommt, lässt sich aber auch an keinem anderen Beispiel, als diesem Beispiel, demonstrieren!? Spezialfälle taugen nichts für Regeln...
Worauf willst du hinaus? Dass der abschliessende Strichpunkt im Block auch in Pascal moeglich ist, habe ich doch schon eingestanden.

Du schaust auf die Spezialfaelle an der Oberflaeche, ich schaue auf die Struktur der Sprache. In C sind Strichpunkte Statement-Terminatoren. In Pascal sind Strichpunkte Statement-Separatoren. (In awk sind es ebenfalls Statement-Terminatoren, die durch Newlines ersetzt werden koennen.)

Dass man den abschliessenden Strichpunkt vor dem Blockende auf beiden Wegen erreichen kann -- bei C regulaer und bei Pascal ueber den ``Sonderfall'' eines leeren Statements -- aendert nichts daran, dass die Sprachen eine grundsaetzlich unterschiedliche Auffassung von Strichpunkten haben.


C: https://cs.wmich.edu/~gupta/teaching/cs ... 20form.htm

Code: Alles auswählen

<compound-statement> ::= { {<declaration>}* {<statement>}* }

<statement> ::= <labeled-statement>
              | <expression-statement>
              | <compound-statement>
              | <selection-statement>
              | <iteration-statement>
              | <jump-statement>

<labeled-statement> ::= <identifier> : <statement>
                      | case <constant-expression> : <statement>
                      | default : <statement>

<expression-statement> ::= {<expression>}? ;

Pascal: http://www.cs.kent.edu/~durand/CS43101F ... -EBNF.html

Code: Alles auswählen

statement-part =
    begin statement-sequence end . 

statement-sequence =
    statement { ";" statement } . 
statement =
    [ label ":" ] (simple-statement | structured-statement) . 
simple-statement =
    [ assignment-statement | procedure-statement | goto-statement ] . 
    

Wenn du dir den Post von eggy anschaust und den Kommentar am Ende, wo eine Pascal-Idee bezueglich Strichpunkten vermittelt wird, die so konzeptionell fuer awk nicht zutrifft, verstehst du warum ich darauf eingestiegen bin. Auch wenn mein Beispiel nicht vollstaendig korrekt war habe ich doch den Unterschied der Syntax-Konzepte vermittelt.
eggy hat geschrieben: ↑ zum Beitrag ↑
03.07.2020 17:01:13
@desputin:
Awk kann man als "Einzeiler" oder mit script Datei nutzen.
Das gleiche wie oben nochmal in lesbar, so wird vielleicht besser klar, was da passiert

Code: Alles auswählen

BEGIN {
                FS = "[<>]" ;
                z=0; 
                email[z]="email";
                nummer[z]="nummer"; 
                oldfile=""
}  


{
                if (FILENAME!=oldfile) {
                                z=z+1; 
                                oldfile=FILENAME
                }
}


/MaStR/{ 
                for (i=NF; i>0; i--){ 
                                if (substr($i,0,3)=="SNB") { 
                                                gsub("[^0-9]","",$i); 
                                                nummer[z]=$i
                                } 
                }
}  

/tr class="detailstammdaten email"/{ 
                for (i=NF; i>0; i--){ 
                                if (index($i,"@") != 0) {
                                                email[z] =  $i 
                                }
                }
}

END{
                for ( i = 0; i <= z; i++) {
                                print  nummer[i] ";" email[i] 
                } 
}

awk -f script.awk *.html

Merkwürdigkeit am Rande: das ";" am Zeilenende ist nur nötig, wenn ein weiterer Befehl folgt.
Use ed once in a while!

tobo
Beiträge: 2349
Registriert: 10.12.2008 10:51:41

Re: Grep nach zwei Parametern und in eine CSV-Datei...

Beitrag von tobo » 04.07.2020 09:59:55

Meillo hat geschrieben: ↑ zum Beitrag ↑
04.07.2020 08:51:32
Du schaust auf die Spezialfaelle an der Oberflaeche, ich schaue auf die Struktur der Sprache.
Das habe ich halt - gerade durch dein freepascal-Beispiel - genau andersrum gesehen. Aber ok, ich denke, dass ich jetzt verstanden habe, was du meinst.

Antworten