Regex: ersetze ;) falls davor nicht abc steht
Robert
- programmiertechnik
Hallöle,
ich will die Zeichenfolge ;) durch ### ersetzen - aber nur für den Fall, daß vor dem ;) nicht abc steht:
Aus
abc;) ;) def;)
soll also
abc;) ### def###
werden.
Ok, normales Ersetzen von ;) ist ja kein Problem:
Finde ;) Ersetze durch ###
Damit wird natürlich auch aus abc;) dann abc###
Also hab ich probiert, eine "negative lookahead assertion einzusetzen:
Finde (?!abc);) Ersetze durch ###
Ergebnis:
abc### ### def###
Hm. Was mache ich falsch?
In der Hilfe des Tools (WildEdit) heißt es:
"(?!abc)" matches zero characters only if they are not followed by the expression "abc".
Also dürfte die erste Ersetzung doch gar nicht stattfinden.
Einen Bug in WildEdit schließe ich aus, da PHP mit preg_replace dasselbe Ergebnis bringt.
cu,
Robert
hi,
Also hab ich probiert, eine "negative lookahead assertion einzusetzen:
die ist hier aber fehl am platze - du brauchst eine lookbehind assertion:
Finde (?!abc);) Ersetze durch ###
Ergebnis:
abc### ### def###
finde: (?<!abc);)
ersetze durch: ###
ergebnis: abc;) ### def###
In der Hilfe des Tools (WildEdit) heißt es:
"(?!abc)" matches zero characters only if they are not followed by the expression "abc".
was heißt denn "not _followed_" - ist es das, was du bezwecken wolltest?
gruß,
wahsaga
Hallöle,
Also hab ich probiert, eine "negative lookahead assertion einzusetzen:
die ist hier aber fehl am platze - du brauchst eine lookbehind assertion:
Aha - die kannte ich noch nicht - Wildedit unterstützt die nicht.
finde: (?<!abc);)
ersetze durch: ###
ergebnis: abc;) ### def###
Ok, im PHP klappt das - muß ich halt damit statt mit Wildedit arbeiten.
In der Hilfe des Tools (WildEdit) heißt es:
"(?!abc)" matches zero characters only if they are not followed by the expression "abc".
was heißt denn "not _followed_" - ist es das, was du bezwecken wolltest?
Nö, nicht wirklich.
aber die neg. lookahead assertion war das einzige, was ich in der Wildedit-Hilfe gefunden hab, was zwar prüft, ob die Zeichen vorhanden sind, diese aber nicht in den match aufnimmt.
Ich danke Dir für diese "Rücksichtnahme" ;-)
Also mit konstantem String abc klappt es jetzt.
Leider beschwert sich PHP, wenn ich statt des konstanten Strings alternativ unterschiedlich lange Strings benutze:
(?<!(abc|de|ghij));)
da kommt dann eine Warnung:
Compilation failed: lookbehind assertion is not fixed length at offset 16 in <filename> on line <linenumber>
(der Offset scheint sich auf die schließende Klammer der Alternative zu beziehen)
(?<!&(amp|gt|lt|quot));)
ist das, was ich eigentlich bräuchte (was aber nicht funktioniert wegen der unterschiedlichen Längen).
cu,
Robert
Hallo Robert,
(?<!&(amp|gt|lt|quot));)
ist das, was ich eigentlich bräuchte (was aber nicht funktioniert wegen der unterschiedlichen Längen).
Da gibt es zwei Lösungenswege:
1. Eine brauchbare Regex-Implementierung verwenden ;-)
Die von Java kann das z.B. Perl hingegen kann es auch nicht.
2. Entityreferenzen auch matchen und hinterher entscheiden, ob ersetzt wird
Beispiel in Perl:
$text =~ s/(&(?:amp|gt|lt|quot))?;/$1 ? $1.':' : 'was anderes'/ge;
Grüße
Daniel
Hi,
- Eine brauchbare Regex-Implementierung verwenden ;-)
Hm. Sagt sich so einfach ...
- Entityreferenzen auch matchen und hinterher entscheiden, ob ersetzt wird
Beispiel in Perl:$text =~ s/(&(?:amp|gt|lt|quot))?;/$1 ? $1.':' : 'was anderes'/ge;
Hm. Meine Perl-Kenntnisse sind zu gering, um zu verstehen, was da abgeht.
Trotzdem danke - ich werd erstmal die Variante von Christian probieren.
cu,
Andreas
Hallöle,
sorry, Andreas - ich hab vergessen, Dich auszuloggen (danke, daß ich Deinen Compi nutzen darf, solange mein Inetzugang down ist).
cu,
Robert
Hi,
sorry, Andreas - ich hab vergessen, Dich auszuloggen (danke, daß ich Deinen Compi nutzen darf, solange mein Inetzugang down ist).
Was nutzt Du auch meinen Firefox, wo ich Dir doch extra Deinen geliebten Opera installiert hab …
cu,
Andreas
Hallo Robert,
$text =~ s/(&(?:amp|gt|lt|quot))?;/$1 ? $1.':' : 'was anderes'/ge;
s/regex/code/ge ersetzt einfach das, was der reguläre Ausdruckt matcht durch das Ergebnis des Codes.
$1 ? $1.';' : 'was anderes' ist einfach ein inline-if. Wenn $1 definiert ist, wird einfach durch das ersetzt, was gematcht wurde. Statt $1.';' könnte man in dem Fall natürlich auch $0 nehmen, fällt mir da auf.
Grüße
Daniel
Hallo Robert,
Leider beschwert sich PHP, wenn ich statt des konstanten Strings alternativ unterschiedlich lange Strings benutze:
(?<!(abc|de|ghij));)
da kommt dann eine Warnung:
Compilation failed: lookbehind assertion is not fixed length at offset 16 in <filename> on line <linenumber>
(der Offset scheint sich auf die schließende Klammer der Alternative zu beziehen)
Es gibt noch einen dritten Lösungsweg (außer denen, die Daniel beschrieben hat):
(?<!abc)(?<!de)(?<!ghij);)
Da eine Lookbehing-Assertion die Länge 0 hat, kannst Du da auch mehrere hintereinander schreiben, wenn Du sonst den Inhalt mit | trennen würdest. Achtung allerdings: die Menge der Lookbehind-Assertions ist begrenzt und außerdem verlangsamt jede weitere Assertion den Ausdruck. Daher: dort, wo Du zusammenfassen kannst, weil die Teile die gleiche Länge haben, solltest Du das ganze in eine Assertion packen, also bei Deinem Enity-Ausdruck:
(?<!")(?<!&)(?<!&(lt|gt));)
Viele Grüße,
Christian
Hallöle,
Es gibt noch einen dritten Lösungsweg (außer denen, die Daniel beschrieben hat):
(?<!abc)(?<!de)(?<!ghij);)
(?<!")(?<!&)(?<!&(lt|gt));)
Juhuu! Das funktioniert.
Muchas Gracias, geniale Idee, da mehrere von den Dingern aneinanderzureihen.
cu,
Robert