Robert: Regex: ersetze ;) falls davor nicht abc steht

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

  1. 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

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. 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

      1. 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

        1. Hi,

          1. Eine brauchbare Regex-Implementierung verwenden ;-)

          Hm. Sagt sich so einfach ...

          1. 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

          --
          Warum nennt sich Andreas hier MudGuard?
          Schreinerei Waechter
          Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
          1. Hallöle,

            sorry, Andreas - ich hab vergessen, Dich auszuloggen (danke, daß ich Deinen Compi nutzen darf, solange mein Inetzugang down ist).

            cu,
            Robert

            1. 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

              --
              Warum nennt sich Andreas hier MudGuard?
              Schreinerei Waechter
              Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
          2. 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

      2. 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:

        (?<!&quot)(?<!&amp)(?<!&(lt|gt));)

        Viele Grüße,
        Christian

        1. Hallöle,

          Es gibt noch einen dritten Lösungsweg (außer denen, die Daniel beschrieben hat):

          (?<!abc)(?<!de)(?<!ghij);)
          (?<!&quot)(?<!&amp)(?<!&(lt|gt));)

          Juhuu! Das funktioniert.

          Muchas Gracias, geniale Idee, da mehrere von den Dingern aneinanderzureihen.

          cu,
          Robert