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

Fragen zu Regular Expressions

byron1778

Hacker
Hallo,

ich habe ein paar Probleme mit den Regular Expressions.
Ich habe folgendes Beispiel: Anders Helga 0262/2781
Reg.Expression dazu:1, $/\([a-zA-Z])\) \(a-zA-Z\)/\2 \1/
Ausagbe:Helga Anders

Kann mir jemand erklären warum sich hier die Namen drehen?
Ich habe schon überall nachgesehen aber ich komme nicht darauf?!?!?

Und ein letztes Beispiel:
Hermann Meier
Meier Thomas
Meier
meier hannes

Reg. Expr: 1,$s/^Meier/Müller/

Ausgabe: Hermann Meier
Müller Thomas
meier hannes

Wie kann es sein dass die 3te Zeile gelöscht wird?
Lt. dem ^ müsste ja die 3te Zeile ersetz werden mit Müller, nicht?
Kann es sein, dass man sich hier geirrt hat?-habe es vom Prof. bekommen!

Danke wenn mir jemand weiterhelfen kann!

Mfg
Byron
 

regexer

Advanced Hacker
Ich habe folgendes Beispiel: Anders Helga 0262/2781
Reg.Expression dazu:1, $/\([a-zA-Z])\) \(a-zA-Z\)/\2 \1/
Ausagbe:Helga Anders
Ersteinmal die Frage: Was für eine Sprache verwendest du da? Da es sich bei "1, $" um eine sed-Zeilennotation handelt, vermute ich "sed". Wenn nicht, bitte bescheidgeben.
Falls es wirklich sed ist, funktioniert das Beispiel sowieso nicht.
Erstens ist da mindestens eine runde rechte Klammer zuviel drin.
Zweitens fehlt der eigentliche Befehl (nämlich "substitute" oder kurz "s").
Drittens muss dann das zweite "a-zA-Z" auch in eckige Klammern.
Viertens sollte - damit sich Helga dreht - nach den eckigen Klammern jeweils ein Stern kommen.
Fünftens kann man das "1,$" weglassen, da es einfach nur heißt: Von der ersten bis zur letzten Zeile. Und das ist beim sed Standard.

So! Jetzt funktioniert es sogar auf der Kommandozeile wiefolgt:
Code:
echo "Anders Helga 0262/2781" | sed 's/\([a-zA-Z]*\) \([a-zA-Z]*\)/\2 \1/'
Nun zur Erklärung: Das erste a-zA-Z landet einen treffer auf "Anders". Die Klammern gruppieren diesen Treffer und legen in in die Varialbe \1. Das zweite a-zA-Z trifft auf Helga zu. Da dieser Treffer von dem zweiten runden Klammernpaar eingeschlossen ist, wird dieser Treffer durch \2 symbolisiert. Und jetzt kann man im "Ersetzen-Teil" die Treffer einfach umtauschen, indem du den zweiten vor den ersten setzt.
Alles klar?

Und ein letztes Beispiel:
[...]
Kann es sein, dass man sich hier geirrt hat?
Ja!
 

oc2pus

Ultimate Guru
Du kannst zum "üben" von regex wunderbar dieses Tool einsetzen:

http://txt2regex.sourceforge.net/

Txt2regex is a Regular Expression Wizard that converts human sentences to regexes. In a simple interactive console interface, the user answer questions and the program build the regexes for more than 20 programs, like Vim, Emacs, Perl, PHP, Python, Procmail and OpenOffice.org. It is a Shell Script 100% written with Bash builtin commands. No compilation or extra commands are needed, just download and run.
 
OP
B

byron1778

Hacker
Sorry, daß ich es falsch notiert habe, war doch schon ein wenig spät, aber jetzt verstehe ich es!

Danke für die großartige Hilfe!

Mfg
Byron
 

regexer

Advanced Hacker
byron1778 schrieb:
Sorry, daß ich es falsch notiert habe, war doch schon ein wenig spät,
Warum spät? Ist doch eine normale Zeit für angehende Informatiker :wink:

Im Zusammenhang mit Regular Expressions ist es immer gut, die verwendete Scriptsprache oder den verwendeten Editor anzugeben. Vom Prinzip her ist zwar die Logik of dieselbe, aber bei der Notation gibt es schon ein paar Unterschiede.

BTW: Am liebsten regechse ich natürlich in perl.
 
OP
B

byron1778

Hacker
Ok, wenn das die richtige Uhrzeit ist, dann werde ich meine Schlafphasen nun ein wenig verschieben! :)

Eine allerletzte Frage noch bzgl. sed und dem vertauschen.

Ich habe folgende Angabe:

Name Zuname PLZ Ort

und diese sollen vertauscht werden nach.

PLZ Name Ort Zuname


Wie kann ich hier mehrere Angaben vertauschen?

Vielleicht so?:

sed 's/\([a-zA-Z]*\) \([a-zA-Z]*\) \([0-9]*\) \([a-zA-Z]*\) /\3 \1 \1 \2 \2 \4 \3 \1 \4 \3/'

Aber irgendwie kann ich mir das nicht vorstellen!

Eine letzte Hilfe noch bitte.

Danke und mfg
Byron
 

regexer

Advanced Hacker
byron1778 schrieb:
Vielleicht so?:

sed 's/\([a-zA-Z]*\) \([a-zA-Z]*\) \([0-9]*\) \([a-zA-Z]*\) /\3 \1 \1 \2 \2 \4 \3 \1 \4 \3/'

Aber irgendwie kann ich mir das nicht vorstellen!
Nein.
Erstens das Blank hinter der letzten runden Klammer weglassen. Sonst wird nach Blank gesucht und wenn die Zeile kein trailing blank hat wird sie ignoriert.
Zweitens: Warum druckst du im Ersetzen-Teil jedes Feld insgesamt drei mal? Das würde schon ohne Fehler durchlaufen, aber die erhälst folgende Ausgabe:
Code:
PLZ Name Name Zuname Zuname Ort PLZ Name Ort PLZ
Die Logik ist also nicht: tausche \3 mit \1, dann \1 mit \2, dann...
Sondern:Drucke \3, dann ein Space. dann \1, dann ...
 
OP
B

byron1778

Hacker
Ok, danke

Damit sind glaube ich nun alle meine Fragen beantwortet, das schlimme ist, daß wir Musterbeispiele bekommen haben, aber dabei etliche Fehler sind und ich schon nicht mehr weiss, wann was richtig ist.

Danke nocheinmals.

Lg
Byron
 

regexer

Advanced Hacker
Noch ein Hinweis: Zur Übung sind solche Beispiele vielleicht ganz gut. Aber in der Realität wird man wohl kaum eine solche RegExp für Anschriften verwenden.
Beispiel:

Jürgen P. Richter-Groß D-12345 Bad Sonstwo

... und schon findet die RegExp gar nichts mehr. Probleme sind hier.
- Der Vornamen enthält einen Umlaut
- Der Vornamen besteht aus zwei Teilen
- Der Punkt gehört mit zum Vornamen
- Der Nachname enthält Bindestrich und Umlaut
- Die PLZ enthält einen Buchstaben und einen Bindestrich
- Der Ort besteht aus zwei Wörtern

Man könnte das Beispiel noch beliebig fortsetzen:
- Polnische oder Portugiesische PLZ werden gegeliedert
- Wenn man die Straße und Hausnummer noch hinzunehmen würde ging hier das Spielchen auch noch weiter:
--> Manche Straßennahmen bestehen aus mehreren Wörtern "Am Fuchsberg"
--> manche Orte haben nur eine Straße, da darf die Straße dann leer sein
--> Manche Orte haben Zahlen im Straßennamen (z.B. Mannheim, Berlin)
--> Die Hausnummer kann alle möglichen Buchstaben und Sonderzeichen enthalten und kann obendrein gegliedert werden

usw. usf.
 

TeXpert

Guru
naja, mit den Sonderzeichen ist das i.A. kein Problem, es kommt dann nur darauf an, die richtigen Zeichenklassen zu nehmen:

Code:
$ echo "Müller Jürgen 12345 Hamburg" | sed -e 's#\([[:alpha:]]*\) \([[:alpha:]]*\).*#\2 \1#'
Jürgen Müller

alternativ kann man bei diesem Beispiel auch die Trenner " " nehmen:
Code:
$ echo "Müller Jürgen 12345 Hamburg" | sed -e 's#\([^ ]*\) \([^ ]*\).*#\2 \1#'
Jürgen Müller

damit gehe ich natürlich immer von einer parsebaren Syntax aus, wenn ich jetzt nicht anhand von eindeutigen Kriterien unterscheiden kann wie die Felder getrennt sind, also entweder mit einem "Trennsymbol" oder durch eine definierte Zeichenklasse aus der ein einzelner Eintrag besteht kann man das nicht automatisch parsen.

In solchen Fällen ist eine eindeutige Syntax notwendig -> Stichworte Grammatiken, Chomsky-Sprachen, etc.
 
Oben