Regex

regex7

Reguläre Ausdrücke sind in unserem Studium leider etwas stiefmütterlich behandelt worden. Das sie ein Mächtiges Werkzeug sein können wusste ich aber schon immer. Leider habe ich bis heute a) keine Fall gehabt wo ich es wirklich gebraucht habe und b) niemanden gehabt den ich notfalls fragen konnte. Heute war nun der Fall das a) und b) zusammen aufgetreten sind. Hier ein Tutorial wie es funktioniert.

Ich sollte auf Arbeit stupides Copy&Paste von Vorlagen eines alten Systems in die Vorlage des neuen Systems “übersetzen”. Ohne Regex hätte ich die vielen Datein händisch durchsuchen müssen und jedes mal Ersetzungen durchführen – wenn angebracht. Das schrie förmlich nach regulären Ausdrücken.

Bevor ich euch jetzt erkläre wie mein Verständnis evolviert ist lest bitte dieses Tutorial bei regenechsen.de. Dort die Minimumvoraussetzungen. Das [a-zA-Z]* belieblige Zeichenketten die nur aus Buchstaben bestehen, will ich hier nicht erklären, das steht dort sehr gut geschrieben.

Meine Aufgabe:

Ersetze alles was bisher <?=$variable?> war (php für die Rückgabe des Wertes einer Variable) sollte jetzt {variable} werden. Also im Grunde <?= finden und durch { ersetzen, dann bis zum Ende gehen und das ?> ersetzen. Wichtig ist das alle anderen php Befehle nicht beachtet werden sollten. Also <?=__(‘hallo_welt’)?> sollte <?=__(‘hallo_welt’)?> bleiben.

Das Ganze passiert bei mir in Eclipse sollte aber so oder sehr änhlich in einer Programmiersprache auch funktionieren. Die Screenshots sind aus dem Finden/Ersetzen Dialog direkt aus Eclipse. Dort kann man per Checkbox festlegen, dass reguläre Ausdrücke verwandt werden.

1. Schritt: einfaches Suchen Ersetzen

klappt nicht denn wenn ich nach ?> suche werden auch die ungewollten Fälle ersetzt. <?=__(‘hallo_welt’)?> würde ebenso ersetzt wie <?=$hallo_welt?>.

regex1

einfaches Suche&Ersetzen

2. Schritt: reguläre Suche nach “Buchstabe + “?>”

“Buchstabe” als regex: \w

?> als regex: \?\> (Sonderzeichen werden mit Backslash maskiert)

also \w\?\> findet mir alle diese Vorkommen. wenn ich nun ersetze hab ich das Problem das mein Buchstabe auch ersetzt wird.

regex2

Wichtig: Regular expressions muss angekreuzt sein!!!

3. Schritt: aufteilen

Klammern können eine regex in Teile aufsplitten. die Teile kann ich dann vertauschen/ersetzen wie ich lustig bin.

(\w)\?\> findet meine Gruppe und der Buchstabe ist in Klammern also kann ich mit $1 in der Ersetzung Dinge machen

(\w)(\?\>) teilt das erbgebnis in 2 Gruppen… mit $1 kann man die erste Gruppe ansprechen.

regex3

Regex checkbox ausgeblendet aber aktiv!

Dies findet also das Ende meines Ausdruckes und lässt den Buchstaben stehen, und ersetzt mein Fragezeichen und das Größerzeichen.

aus foo?> wird foo}

4. Schritt: Anfang+Ende in einer Regex

Da ich das Ende sehr gut ersetzen kann wollte ich nicht noch eine 2. regex bauen, die den Anfang findet und ersetzt. Also habe ich mir gesagt ich bauen EINE regex die den Anfang findet, das Zwischenteil identifiziert und dann den Ende findet.

(\<\?\=\$)([a-zA-Z]+)(\?\>) ist das Erbenis

(\<\?\=\$) für den Anfangsteil also <?=

([a-zA-Z]+) für eine Zeichenkette aus Buchstaben, mindestens ein Buchstabe lang

(\?\>) für den letzen Teil also ?>

Durch Klammern getrennt ist das sogar halbwegs übersichtlich. Man stelle sich das ganze ohne Klammern vor.

Wenn ich das nun mit \{$2\} ersetze klappt das ganze schon ganz gut.

regex4

aus <?=$eineVariable?> wird {eineVariable}

5. Schritt: Feintuning

Nun habe ich bemerkt das auch Unterstriche und Zahlen in der Zeichenkette in der Mitte vorkommen dürfen. also:

(\<\?\=\$)([0-9a-zA-Z\_]+)(\?\>)

([0-9a-zA-Z\_]+) für eine Zeichenkette aus Buchstaben, Zahlen und Unterstrichen mindestens ein Buchstabe lang. Der Anfang- und Endteil bleiben gleich.

regex5

aus <?=$eine_Variable2?> wird {eine_Variable2}

6. Schritt: Anderes Muster nach ähnlichem Prinzip finden und ersetzen

Nun habe ich mittendrin beim Ersetzen gemerkt, dass ich auch %%foo%% durch {foo} ersetzen muss. Also eine 2. regex für den neuen Fall:

replace (\%\%)([0-9a-zA-Z\_]+)(\%\%) with \{$2\}

das sollte sehr einfach sein, wenn man die ersten 5 Schritte kapiert hat. 

aus %%ein_variable23%% wird {eine_variable23}

Theoretisch sollte sich auch eine Regex finden die beide Fälle behandelt weil sie so sehr verwandt sind. Wer lust hat, schreibt die Lösung bitte in die Kommentare.

vielen Dank an dieser Stelle an David, unserem Serverguru.

4 Kommentare

  1. Simi sagt:

    {klugscheiss begin}
    Du bist dir aber bewusst, dass, z.B. “$this->classvar” als Variable nicht ersetzt wird, ja?
    Und die Regex, die beide Fälle behandelt, hast du doch schon im Screenshot ganz oben gepostet hast?!
    {klugscheiss end}

  2. Falko sagt:

    Diese Art von Variablen wurde nicht verwandt. Ich hab aber gedacht, dass die Lösung der letzten Frage etwas schwieriger wird 🙁 Du bist einfach zu gut Simi

  3. Andy sagt:

    {rechthaben ein}
    hey hey hey, du weißt aber schon, dass ich schon viiiieeeel früher drauf gekommen bin, oder?!
    {rechthaben aus}

    😉

  4. Falko sagt:

    FYI unter http://www.txt2re.com kann man auch sehr nett sich regular expressions generieren lassen