EisFuX: ... und was is mit Kommentaren?

Beitrag lesen

(H(all|ih)o|(Gudn\s)?Ta(g|ch)) seth_not@home,

Vorweg: Interessant, was aus einem schlecht strukturiertem PHP-Handbuch
so alles für Probleme entstehen. Wären die POSIX-kompatiblen RegEx dort
so umfangreich abgehandelt worden wie die PCRE, hätte sich die Verwirrung
sicher in Grenzen gehalten, und man hätte hier wahrscheinlich wieder nur
die Einschränkungen bei den negativen Lookbehind-Assertions breitgetreten.

Und dann glaubst du, dass dieses Suchmuster funktioniert?

$suchmuster = "(?<!<[^<>]*)banane(?![^<>]*>)";

angenommen ereg haette keine probleme mit negative assertions variabler laenge (so wie z.b. der texteditor vim, der kann naemlich in dieser hinsicht erstaunlicher mehr als perl), dann sollte diese regexp imho funzen.

Ich hatte angenommen, dass die ereg-Funktionen überhaupt nichts mit
Assertions am Hut haben. Diese Annahme beruht aber lediglich auf
der Tatsache, dass ich das im PHP-Handbuch verlinkte Dokument zu
den Posix-Regexen erfolglos nach "assert"
durchsucht habe ...
http://www.tin.org/bin/man.cgi?section=7&topic=REGEX

in vim waere das regexp-pattern uebrigens
  s/(<[^<>]*)@<!banane([^<>]*>)@!/abbl/g
und hat einen kleinen test von mir bestanden.

Umfasst der Test auch HTML-Kommentare?

(iow: vim ist toll!)

Ooch, wenn dein erster Computer serienmäßig eine Maus gehabt hätte,
wärst du so bequem wie ich und würdest zum Wechseln auch wesentlich
mehr Anreize benötigen. ... und ich wette, über kurz oder lang kann
PSPad das auch. Vielleicht kann er das schon, ich hab nur den passenden
Menüpunkt noch nicht gefunden.
;-)

kurzer versuch einer erklaerung; ich denke, dass der parser folgendermassen vorgeht:

Man könnte natürlich auch Google nach "reguläre ausdrücke in c# assertion" fragen
und dann bspw. das hier finden:
http://mojo-corp.de/regulaere_ausdruecke_c_sharp.html

Ich gehe davon aus, dass der irgendwo in diesem Thread erwähnte
RegexDesigner.NET diese RegEx-Sprache spricht.

  1. "banane" suchen.
  2. schauen, ob davor irgendwie das pattern <[^<>]* angewendet werden kann.
  3. falls ja: doofe "banane"; weiter bei punkt 2. (naechste "banane" suchen)
  4. falls nein: oha, kanditat gefunden. ueberpruefe restliches pattern.
  5. ist es moeglich, nach der "banene" das pattern [^<>]*> matchen zu lassen?
  6. falls ja: doofe "banane"; weiter bei punkt 2. (naechste "banane" suchen)
  7. falls nein: yeah, die "banane" erfuellt alle kriterien, um ersetzt zu werden.

$muster = '/banane(?=[^>]*<[^>]+>)/i';
$ersatz = 'ananas';
$ergebnis = preg_replace($muster, $ersatz, $heuhaufen);

scheitert an
  "banane"
weil danach nie mehr eine spitze klammer kommt.

Ich zitiere mal, worauf sich meine "Lösung" bezieht:

es soll im htmlquellcode das wort banane überall ersetzt werden nur nicht in attributen und tags!

In halbwegs validem HTML sollte es eigentlich immer ein "</html>" am Ende des Dokuments geben, oder?

In dem Falle würde der RegEx aber sicher über Kommentare stolpern.

Um 100-prozentig sicher zu gehen, müsste man wahrscheinlich das HTML in Tokens (Tag, Nicht-Tag, Kommentar, ...)
zerlegen und dann nur in den Nicht-Tag-Bereichen ersetzen.

besser:
http://www.php-faq.de/q/q-regexp-ersetzen.html

Ich bin Fan sowohl von "/e" als auch von preg_replace_callback().
Allerdings hat mein Ansatz den Vorteil, dass er bis auf einen
geänderten RegEx und den Austausch von eregi_replace() durch
preg_replace() keinerlei Änderungen am Script braucht. Und somit
hab ich mir auch eine Menge Erklärungen erspart, denn spätestens,
wenn im Ersetzen-String wundersame Zeichen auftauchen, die "escape[dt]"
werden müssen, wird die Variante mit "/e" erklärungsintensiv oder
zumindest unpraktisch.

MffG
EisFuX