sipsip
Goto Top

Bash: Email und Name auslesen

Hallo zusammen

Brauche eure Hilfe, verzweifle fast...

Muss aus einer grossen csv Datei mit HTML Inhalt E-Mail Adresse und Name, Vorname auslesen. Das ganze auf Unix mit Bash...

Nun habe ich es geschafft alle E-Mail Adressen auszulesen und zwar mit folgendem code:
#/bin/bash

if [ -f "$1" ]; then  
  grep -o '[[:alnum:]+\.\_\-]*@[[:alnum:]+\.\_\-]*' "$1" | sort | uniq -i >>'/script/result/adressen-$(date "+%d-%m-%Y").csv'  
else
  echo "Expected a file at $1, but it doesn't exist." >&2  
   exit 1
fi

nun fehlt mir noch der Name und Vorname der Person.
Der HTML Code sieht ungefähr immer gleich aus:
<td valign=""top"">  
<p class=""Untertitel"">Vorname Name</p>  
<p class=""Ueberschrift3"">blabla</p>  
<p class=""Haupttext"">&nbsp;</p>  
<p class=""Haupttext"">Adresse</p>  
<p class=""Haupttext"">PLZ Ort</p>  
<p class=""Haupttext"">Tel</p>  
<p class=""Haupttext"">Mobile</p>  
<p class=""Haupttext"">E-Mail Adresse</p>  
</td>

Struktur: Name und Vorname sind immer im <p class=""Untertitel""></p>, jedoch sind auch solche Untertitel einträge vorhanden die nichts mit dem zu tun haben.

Da nicht wirklich eine genaue Struktur zu erkennen ist und im nachhinein erkennlich sein soll welcher Name zu welcher Adresse gehört funktioniert das laut einem Kollegen nicht mit meinem grep Script...

Ich hatte schon für dieses kleine Script ein ganzen Tag da ich Neuling bin und wäre sehr dankbar wenn mir jemand helfen könnte...

Vielleicht gibt es ja eine Lösung wie such mit regex oder sowas nach der E-Mail Adresse und geh dann zurück zum 1 Untertitel und nimm den Namen...

Content-Key: 227550

Url: https://administrator.de/contentid/227550

Printed on: April 16, 2024 at 08:04 o'clock

Member: Lochkartenstanzer
Lochkartenstanzer Jan 23, 2014, updated at Jan 24, 2014 at 08:36:10 (UTC)
Goto Top
Moin,

cat testdatei | sed -e "s:</p>:|:g" -e 's:<p class=""Untertitel"">:|:g' -e "s:<p.*>::g"  | sed -e :a -e "$!N;s/\n//g;ta" | gawk -F "|" ' { print $2 ";" $9 } '

face-smile


lks

nachtrag:

ergibt auf das oben abgegebene Format:

Vorname Name; E-Mail Adresse
Member: colinardo
colinardo Jan 23, 2014 at 19:21:40 (UTC)
Goto Top
Hallo SIPSIP,
cat "testdatei.txt" | tr -d "\n" | sed 's/<td valign=""top"">/\n/g' | gawk 'BEGIN {names="";mail=""}; match($0,/<p class=""Untertitel"">([^<]*)<\/p>/,arr){names=arr[1]};match($0,/([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+)/,arr_mail){mail=arr_mail[1]; print names"|"mail;}'  
gibt dir die Daten mit Pipe-Zeichen voneinander getrennt so aus:
Max Mustermann|max@mustermann.de
Herbert Meier|herbert@meier.com
Grüße Uwe
Member: Endoro
Endoro Jan 23, 2014 at 20:01:59 (UTC)
Goto Top
Hey,

ich finde, das ist für einen Anfänger zu schwer.
sed -nr '/Untertitel/{s/<[^>]+>//g;h};/\<[!#$%&'*+./0-9=?_`a-z{|}~^-]+@[.0-9a-z-]+\.[a-z]{2,6}\>/I{s/<[^>]+>//g;x;G;s/\n/ /p}' file.txt  
Viel Glück!
Member: SIPSIP
SIPSIP Jan 24, 2014 at 07:26:52 (UTC)
Goto Top
Schon mal vielen Dank Leute ihr seit wahrscheinlich meine Rettung face-smile
Ich probier die mal aus

PS: Ja das sehe ich genau so, dass das zu schwer für mich als Anfänger ist... wusste nichtmal mit welchen Kommandos ich das überhaupt hinbekomme.
Member: SIPSIP
SIPSIP Jan 24, 2014 at 07:45:05 (UTC)
Goto Top
Hallo Uwe vielen Dank für deine Bemühungen... face-smile
Deine Lösung gefällt mir am besten und sie funktioniert so weit auch am besten.

Leider aber doch nicht ganz, weil ich bekomme nur folgendes Ergebnis:
 | info@domain.ch 

es sollten aber viel mehr Mails sein und der Name Vorname fehlt...

Kannst du mir nochmal helfen oder mir sagen wo ich das im Kommando untersuchen muss?
Ich versteh nun halt das Kommando nicht perfekt hab mich aber nun ein bisschen über sed und awk informiert.
Member: Endoro
Endoro Jan 24, 2014 at 08:00:36 (UTC)
Goto Top
Wenn das @ Zeichen nur in Mails auftaucht, lässt sich das kürzen:
sed -nr '/Untertitel/{s/<[^>]+>//g;h};/@/{s/<[^>]+>//g;x;G;s/\n/ /p}' file.txt  
Gruss.
Member: colinardo
colinardo Jan 24, 2014 updated at 08:22:46 (UTC)
Goto Top
wir haben halt nur einen Ausschnitt aus deiner Datei. Ich habe als Abschnitt-Trenner pro Person das <td valign=""top""> hergenommen. Was hat es eigentlich mit den doppelten Anführungszeichen im Klassennamen auf sich, normal ist das nicht ? Vielleicht ist das der Grund...
Member: SIPSIP
SIPSIP Jan 24, 2014 at 08:23:42 (UTC)
Goto Top
Danke Endoro

Die Abfrage würde wohl funktionieren nur erhalte ich nun noch viel mehr Text, welchen ich nicht gebrauche...

Gruss
Member: Lochkartenstanzer
Lochkartenstanzer Jan 24, 2014 updated at 08:37:42 (UTC)
Goto Top
Zitat von @SIPSIP:

Schon mal vielen Dank Leute ihr seit wahrscheinlich meine Rettung face-smile
Ich probier die mal aus

PS: Ja das sehe ich genau so, dass das zu schwer für mich als Anfänger ist... wusste nichtmal mit welchen Kommandos ich
das überhaupt hinbekomme.

Nützliche sed-Einzeiler.

lks
Member: Endoro
Endoro Jan 24, 2014 at 08:50:49 (UTC)
Goto Top
Ich vermute, deine Beschreibung der Struktur ist nicht hinreichend genau. Lad den Text zum Testen hoch.
Member: SIPSIP
SIPSIP Jan 24, 2014 at 08:54:35 (UTC)
Goto Top
@ Uwe
Aha also gilt dein Script also einfach für eine dieser Abschnitte?
Die doppelten Anführungszeichen sind überall enthalten wo normalerweise nur 1 davon wäre, evtl. hat das was damit zu tun, dass ich diese csv aus einer Joomla MySQL DB exportiert habe. Frag mich nicht wiso man in einer DB Spalte ganze HTML Formulare abspeichert und die Adressen nicht separat in einer Tabelle... keine Ahnung wer sich das überlegt hat -.-

Könnt ich den den Abschnitt auf das ganze File erweitern? oder erkennt es dan nicht mehr welcher Name, Vorname zu welcher Mail gehört?
Member: Lochkartenstanzer
Lochkartenstanzer Jan 24, 2014 at 09:03:32 (UTC)
Goto Top
Zitat von @SIPSIP:

Könnt ich den den Abschnitt auf das ganze File erweitern? oder erkennt es dan nicht mehr welcher Name, Vorname zu welcher
Mail gehört?

Zitier doch mal eine etwas längers Stück aus der Datei, damit wir sehen, auf was wir triggern können. Ich bin dazvon ausgegengen, daß Du eine Datei hast, in der Hintereinander weg die ganzen records im obigen Format abgelegt sind. Wenn Du genauer spezifizierst, könen wir dir auch bessere Lösungen anbieten.

Hast Du eine Textdatei, in denen viele von den obigen Feldern stehen? Und steht dazwischen auch anderer HTML-Code? Stell mal eine Datei hier rein, die ein paar Datensätze mehr hat, damit wir unsere Skripte drauf loslassen können. Alternativ könntest Du natürlich auch das ergebnis unserer Skripte posten, wenn die auf Deine Dateien losgelassen werden.

lks
Member: Lochkartenstanzer
Lochkartenstanzer Jan 24, 2014 at 09:07:44 (UTC)
Goto Top
Muss aus einer grossen csv Datei mit HTML Inhalt E-Mail Adresse und Name, Vorname auslesen. Das ganze auf Unix mit Bash...

Ach ja:

Ist das eine CSV oder eine HTML-Datei. CSV-dateien haben normalerweise Komma, Strichpunkte o.ä. als Feld-Trenner.

udn wenn Du Daten aus eienr MySQL-datei exportierst. Warum machst Du das nicht gleich im richtigen Format, statt ersmal nach HTML zu exportieren und dann nach normalem Text (csv) zu wandeln?

lks
Member: SIPSIP
SIPSIP Jan 24, 2014 at 09:40:30 (UTC)
Goto Top
Also ich hab MySQL mit 96 Datenbanken in denen sind ca.240 Tabellen, davon brauche ich genau eine und davon nur eine Spalte.
Diese Spalte exportiere ich mit folgendem Script in eine CSV Datei (in der Spalte ist HTML Code enthalten). CSV Datei, damit man die Datei mit einem Script durchsuchen kann und die "Enddatei" wo schlussendlich die Namen vorname und Email Adresse enthalten sein soll, muss auch eine CSV sein.
#!/bin/sh

db=dbname
user=root
pass=pw

for table in $(mysql -u$user -p$pass $db -Be "SHOW tables" | sed 1d); do  
echo "exporting $table..."  
mysql -u$user -p$pass $db -Be "SELECT spaltenname FROM tabellenname INTO OUTFILE '/script/db-export-$(date "+%d-%m-%Y").csv'  
FIELDS TERMINATED BY '|'  
LINES TERMINATED BY '\n'"  
done;

Hier noch ein längerer Abschnitt der exportierten CSV Datei:
<tr>
<td><img src=""LINK/></td>  
<td valign=""top"">  
<p class=""Untertitel"">Vorname Name</p>  
<p class=""Ueberschrift3"">blabla</p>  
<p>&nbsp;</p>
<p class=""Haupttext"">adresse</p>  
<p class=""Haupttext"">plz ort</p>  
<p class=""Haupttext"">Tel.</p>  
<p class=""Haupttext"">mail@domain.ch</p>  
</td>
</tr>
</tbody>
</table>"  
"<p class=""Ueberschrift"">blabla</p>  
<p class=""Ueberschrift"">&nbsp;</p>  
<p><img style=""border: 0pt none; margin: 2px;"" src=""LINK"" alt="""" width=""100"" border=""0"" /></p>  
<p>&nbsp;</p>
<p class=""Haupttext"">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolo</p>  
<p class=""Haupttext"">&nbsp;</p>  
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolo</p>
<p>blabla</p>
<ul>
<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, s</li>
<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, s</li>
<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, s</li>
<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, s</li>
</ul>
<p>&nbsp;</p>
<p><a href=""LINK"" target=""_blank"">blabla</a></p>  
<hr />
<p class=""Untertitel"">blabla</p>  
<p>&nbsp;</p>
<table style=""width: 100%;"" border=""0"" cellspacing=""5"" cellpadding=""5"">  
<tbody>
<tr>
<td style=""width: 200px;""><img src=""LINK"" alt="""" border=""0"" /></td>  
<td valign=""top"">  
<p class=""Untertitel""><a name=""NAME""></a>Prof. Dr. Vorname Name</p>  
<p class=""Ueberschrift3"">blabla</p>  
<p>&nbsp;</p>
<p class=""Haupttext"">adresse</p>  
<p class=""Haupttext"">plz ort</p>  
<p class=""Haupttext"">Tel.</p>  
<p class=""Haupttext"">mail@domain.ch</p>  
<p class=""Haupttext"">&nbsp;</p>  
<p class=""Haupttext""><a href=""LINK"" target=""_blank"">blabla</a></p>  
</td>
</tr>
</tbody>
</table>

Mit meinen grep Scritp erhalte ich um die 50 Adressen.

Das Ergebniss von Uwes Script habe ich schongepostet.
Bei Endoros zweitem Script
sed -nr '/Untertitel/{s/<[^>]+>//g;h};/@/{s/<[^>]+>//g;x;G;s/\n/ /p}' file.txt  
erhalte ich eben zu viel Text drum herum...
Bei Lochkartenstanzers Scritp erhalte ich nur ein \ als antwort.
Member: colinardo
colinardo Jan 24, 2014 at 09:57:52 (UTC)
Goto Top
ist ja klar, da ist ja noch ein zusätzliches Link Tag vor dem Namen !!
<p class=""Untertitel""><a name=""NAME""></a>Prof. Dr. Vorname Name</p
das konnte man natürlich nicht ahnen ...
Member: Endoro
Endoro Jan 24, 2014 at 10:02:14 (UTC)
Goto Top
Wenn ich meine sed Zeile auf deinen Text loslasse, erhalte ich:
Vorname Name mail@domain.ch
Prof. Dr. Vorname Name mail@domain.ch
Good luck!
Member: SIPSIP
SIPSIP Jan 24, 2014 at 10:24:21 (UTC)
Goto Top
@Endoro deine sed Zeile funktioniert grundsätzlich, jedoch erscheint auch all der andere Text der in <p class=""Untertitel""> enthalten ist. Ausserdem ist die Ausgabe nicht strukturiert aber vielleicht gelingt es mir ja irgendwie face-smile
Member: Lochkartenstanzer
Lochkartenstanzer Jan 24, 2014 updated at 11:20:40 (UTC)
Goto Top
Kannst du mal den Code ohne Zeilennummerierung reinstellen? (Einfach type=plain in den code-Tag mit rein). Dann kann man das einfach mal mit copy&paste an die sed-zeile verfüttern anstatt das erst in eine textdatei reinzuschieben und dann dann die zeilennummern rauszulöschen.

lks

Nachtrag: Und markiere mal die Tabellenelemete, so daß man sieht, wo jeweils ein Tabelleneintrag beginnt und wo einer endet, damit man einen Anhaltspunkt hat, wie ein einzelner tabelleneintrag aussieht.

Nahctrag2. Kann derjenige, der da auf den --Button geklickt hat mir per PM mal sagen, was ihn an meinem Kommentar stört?
Member: Lochkartenstanzer
Lochkartenstanzer Jan 24, 2014 at 11:56:54 (UTC)
Goto Top
Zitat von @SIPSIP:

Bei Lochkartenstanzers Scritp erhalte ich nur ein \ als antwort.

Wenn ich den obigen textschnipsel an meine Skript-zeile verfüttere bekomme ich:
Vorname Name;</td></tr></tbody></table>""blabla

was machst Du anders?

lks
Member: SIPSIP
SIPSIP Jan 24, 2014 at 12:08:15 (UTC)
Goto Top
Zitat von @Lochkartenstanzer:

Kannst du mal den Code ohne Zeilennummerierung reinstellen? (Einfach type=plain in den code-Tag mit rein). Dann kann man das
einfach mal mit copy&paste an die sed-zeile verfüttern anstatt das erst in eine textdatei reinzuschieben und dann dann
die zeilennummern rauszulöschen.

Ich glaub ich weiss warum er dir ein - gegeben hat...
du kannst bei dem Code oben rechts in der Ecke auf Quellcode klicken, dann erscheint er ohne die Nummerierung ;)
Member: Lochkartenstanzer
Lochkartenstanzer Jan 24, 2014 updated at 12:15:23 (UTC)
Goto Top
Zitat von @SIPSIP:

Ich glaub ich weiss warum er dir ein - gegeben hat...

Jetzt weiß ich es.

du kannst bei dem Code oben rechts in der Ecke auf Quellcode klicken, dann erscheint er ohne die Nummerierung ;)

Das hatte ich vor Deinem Posting nicht bemerkt, obwohl ich schon einige Jahre hier unterwegs bin. Wieder was gelernt. face-smile

lks

Nachtrag: Da ich klickfaul bin, wäre es trotzdem einfacher gleich ohne Nummerierugn reinzusctellen. Dann spart man sich mehrere klicks. face-smile
Member: Endoro
Endoro Jan 24, 2014 at 12:24:02 (UTC)
Goto Top
Zitat von @SIPSIP:

@Endoro deine sed Zeile funktioniert grundsätzlich, jedoch erscheint auch all der andere Text der in <p
class=""Untertitel""> enthalten ist. Ausserdem ist die Ausgabe nicht strukturiert

Von weiterem Text im "Untertitel"-Feld weiss ich nichts, bitte genauer beschreiben. Es wird nur das direkt vor der Mail liegende Feld ausgegeben.

Wenn ich wüsste, wie die Ausgabe strukturiert sein soll ...

Gruss.
Member: SIPSIP
SIPSIP Jan 24, 2014 at 13:12:41 (UTC)
Goto Top
Zitat von @Endoro:
Von weiterem Text im "Untertitel"-Feld weiss ich nichts, bitte genauer beschreiben. Es wird nur das direkt vor der Mail
liegende Feld ausgegeben.

Wenn ich wüsste, wie die Ausgabe strukturiert sein soll ...

Also es kommt im Code auch des öftern vor, dass in <p class=""Untertitel"">blabla</p> auch nur Text (blabla) steht und die "Untertitel" nicht nur für Namen Vorname gebraucht werden...

Struktur der Ausgabe sollte halt irgendwie eine Liste sein name vorname mail oder name, vorname, mail... ist eigentliche egal wie nur halt eine gewisse Struktur
Member: Endoro
Endoro Jan 24, 2014 updated at 13:42:38 (UTC)
Goto Top
Die aktuelle Regel lautet:
1) gib jede Mailadresse aus
2) gib dazu das direkt am nächsten darüber/davor stehende "Untertitel"-Feld aus.

Wenn diese Regel nicht richtig ist, formuliere eine richtige Regel zur Erkennung gültiger "Untertitel"-Felder.

Gruss.
Member: SIPSIP
SIPSIP Jan 24, 2014 at 14:25:37 (UTC)
Goto Top
Ja so lautet die Regel nur ist das einfacher gesagt als getan ;)
Member: Endoro
Endoro Jan 24, 2014 at 15:01:04 (UTC)
Goto Top
Fein, dann habe ich es richtig umgesetzt.
Gruss.
Member: colinardo
colinardo Jan 24, 2014 updated at 16:10:33 (UTC)
Goto Top
kann gerade nicht an mein Linux, aber wenn du möchtest kannst du die Textdateien durch folgendes Powershell-Script jagen:
$pathFiles = "D:\*.txt"   
$pathCSV = "D:\Adressen.csv"  
$list = @()
$regex = [regex] '(?is)<td valign=""top"">\s*<p class=""Untertitel"">.*?([^<>]*?)</p>.*?([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,6})'  
foreach($file in (dir $pathFiles)){
    $subject = gc $file.FullName
    $match = $regex.Match($subject)
    while ($match.Success) {
        $name = $match.Groups[1].Value.trim()
        $mail = $match.Groups[2].Value.trim()
	$list += New-Object PSObject -Property @{"Name"=$name;"E-Mail"=$mail}  
	$match = $match.NextMatch()
    } 
}
$list | export-csv $pathCSV -Delimiter ";" -NoTypeInformation  
es extrahiert die Daten von allen Textdateien in einem Verzeichnis, und exportiert dies dann in eine CSV-Datei. Geht hier mit deinem Demo-Fetzen von oben einwandfrei.

Grüße Uwe
Member: SIPSIP
SIPSIP Feb 14, 2014 at 09:56:31 (UTC)
Goto Top
Hej Leute kleine Frage

hab nun ne Datei wo pro Zeile eine E-Mail Adresse aufgelistet ist.
jedoch sind darunter auch einige falsche Einträge wie z.B. @5xe, m@4, sjs@email.ch die ich nicht brauchen kann.
nurn will diese entfernen nach dem Prinzip, lösche die Zeilen die weniger als 6 Zeichen haben und der Eintrag "sjs@email.ch"...

das müsste doch mit sed funktionieren oder? sed '/<argument>/d' nun weiss ich nicht wie ich das alles da reinpacken soll...
oder bin ich komplett falsch?
Member: Endoro
Endoro Feb 14, 2014 at 12:51:00 (UTC)
Goto Top
Ohne dass ich es aktuell testen kann:

Sed -r '/^.{1,5}$/d;/^sjs@email\.ch$/d' file  
Gruss.