Chris: RegExp: alles außer die Zeile beginnt mit einem best. String?

Hi

Ich versuche gerade mit Regular Expressions eine Textdatei zu durchsuchen, es soll jede Zeile gefunden werden die _nicht_ mit einer bestimmten Zeichenfolge beginnt.

Beispieltext:
Der Baum ist grün.
Die Welt ist klein.
Der Ball ist rund.
Das Haus hat ein Dach.
Ein anderer Zeilenanfang.
Noch ein anderer Zeilenanfang.

Um jede ganze Zeile zu finden die mit "Der Bau" beginnt funktioniert die Syntax "^Der Bau.*". So weit so gut, aber ich muss ja jede Zeile finden die _nicht_ damit beginnt.
Meine Versuche mit "[1].*" oder "[2].*" schlagen fehl da anscheinend die eckigen Klammern die Ausnahmezeichen einzeln übergeben (D, e, r, usw.) und nicht als String (Der Bau).

Funktioniert das überhaupt irgendwie mit Regular Expressions?

Grüße, Chris


  1. ^Der Bau ↩︎

  2. ^(Der Bau) ↩︎

  1. Ich versuche gerade mit Regular Expressions eine Textdatei zu durchsuchen, es soll jede Zeile gefunden werden die _nicht_ mit einer bestimmten Zeichenfolge beginnt.

    perlretut: Looking ahead and looking behind

    Funktioniert das überhaupt irgendwie mit Regular Expressions?

    Ungetestet:

    /^(?!Der Baum).+?$/

    Ansonsten:

    print 'ok' unless (index $str, 'Der Baum') == 0;

    Siechfred

    --
    Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.
    1. Ungetestet:

      /^(?!Der Baum).+?$/

      Top, das hat mir geholfen. Eigentlich brauche ich das nicht für Perl selbst, ich will das in einem Macro für jEdit nutzen.

      So funktioniert es wie gewünscht:
      ^(?!Der Bau).*

      Danke,
      Chris

    2. Sei gelobt, : )

      genau so muss man es machen wenns wartbar sein soll:

      print 'ok' unless (index $str, 'Der Baum') == 0;

      oder wenn man RegEx will:

        
      while (<DATA>) {  
       print unless /^Der Bau/;  
      }  
        
      __DATA__  
      Der Baum ist grün.  
      Die Welt ist klein.  
      Der Ball ist rund.  
      Das Haus hat ein Dach.  
      Ein anderer Zeilenanfang.  
      Noch ein anderer Zeilenanfang.  
      
      

      die index-methode dürfte schneller laufen, ich begreife mittlerweile aber RegExe besser und ziehe sie vor, auch wg der Erweitertbarkeit!

      Grüße
       Kurt

  2. Um jede ganze Zeile zu finden die mit "Der Bau" beginnt funktioniert die Syntax "^Der Bau.*". So weit so gut, aber ich muss ja jede Zeile finden die _nicht_ damit beginnt.

    Meine Versuche mit "[1].*" oder "[2].*" schlagen fehl da anscheinend die eckigen Klammern die Ausnahmezeichen einzeln übergeben (D, e, r, usw.) und nicht als String (Der Bau).

    Du sagts:

    "[3].*"

    ^  Am Anfang
    [^ nicht mit folgenden Zeichen beginnend
    D  ein grosses D
    e  ein kleines e
    r  ein kleines r
       ein Leerzeichen
    B  ein grosses B
    a  ein kleines a
    u  ein kleines u
    ]  Ende der Zeichenklasse
       von dieser Zeichenklasse [^BDaeru ] genau ein Zeichen
    .* gefolgt von null oder beliebig vielen Zeichen.
    $  bis zum Ende

    mfg Beat

    --
                     /|
      <°)))o><      / |    /|
                ---- _|___/ |     ><o(((°>
               OvVVvO    __ |         ><o(((°>
    <°)))o><  /v    v\/  |
     <°)))o>< ^    ^/_/_         ><o(((°>
               ^^^^/___/
    ><o(((°>    ----       ><o(((°>
       <°)))o><                      ><o(((°>o

    1. ^Der Bau ↩︎

    2. ^(Der Bau) ↩︎

    3. ^Der Bau ↩︎

  3. Hello,

    such mal im Archiv nach "negative look behind" oder "Assertion"

    Da wirst Du fündig!

    Ein harzliches Glückauf

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Hallo Tom!

      such mal im Archiv nach "negative look behind" oder "Assertion"
      Da wirst Du fündig!

      Na ja, fündig wird er wohl werden, aber seine Aufgabe ist ein eindeutiger Fall für ein »look ahead«, keinesfalls für ein »look behind«.

      Gruß Uwe

      1. Hello,

        Hallo Tom!

        such mal im Archiv nach "negative look behind" oder "Assertion"
        Da wirst Du fündig!

        Na ja, fündig wird er wohl werden, aber seine Aufgabe ist ein eindeutiger Fall für ein »look ahead«, keinesfalls für ein »look behind«.

        Hat er ja nun auch gebaut. Ich muss da immer noch überlegen, bis ich weiß, welche von beiden die richtige ist...
        Aber im betroffenen Thread steht beides sehr ausführlich beschrieben.

        Ein harzliches Glückauf

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hallo Tom!

          Ich muss da immer noch überlegen, bis ich weiß, welche von beiden die richtige ist...

          Die Problemstellung ist, einen Treffer zu erzielen, wenn eine bestimmte Zeichenkette nicht vorkommt (negative Zeichenkette). Was in aller Regel übersehen wird, was man aber unbedingt wissen muss - dies geht nur unter einer ganz bestimmten Bedingung.
          Die "negative Zeichenkette" muss unmittelbar an eine bekannte Zeichenkette, an ein "bekanntes Musterelement", gekoppelt sein.

          Entweder muss man ein eindeutiges Musterelement unmittelbar vor oder unmittelbar hinter der "negativen Zeichenkette" kennen, alleine mit der "negativen Zeichenkette" geht es nicht, kann es gar nicht gehen.

          Fall 1: bekanntes Musterelement gefolgt von negativer Zeichenkette => Musterelement plus negativer Lookahead
          Fall 2: negative Zeichenkette gefolgt von bekanntem Musterelement  => negativer Lookbehind plus Musterelement

          Im Beispiel ist das "bekannte Musterelement" der Textanfang (bzw. Zeilenanfang), also »^«, gefolgt von der "negativen Zeichenkette", also Fall 1.

          Die Sache ist einfach, es wird nur gedanklich falsch herangegangen. Da wird nur die "negative Zeichenkette" gesehen und das "bekannte Musterelement" vollkommen übersehen. Man muss es genau anders herum angehen.
          Die "negative Zeichenkette" interessiert erst einmal überhaupt nicht, es interessiert zunächst einzig und allein das "bekannte Musterelement", denn dieses muss ich zwingend treffen, also entwerfe ich das entsprechende Musterelement und von mir aus auch gleich das Gesamtmuster. Ob ich dann vor dem "bekannten Musterelement" einen Lookbehind oder nach dem "bekannten Musterelement" einen Lookahead setzen muss, ergibt sich eigentlich von selbst.

          Ich hoffe, ich habe das auf die Schnelle richtig und verständlich erklärt.

          Gruß Uwe

          1. Kurtz gegrüßt

            Ich hoffe, ich habe das auf die Schnelle richtig und verständlich erklärt.

            Nö, ... also obs richtig erklärt wird weiß ich nicht! : )

            Wie auch immer der Ansatz mit "look arounds" zu arbeiten ist IMHO Kanonen-auf-Spatzen Irrsinn.

            Der Matchingausdruck muss außerhalb der RegEx invertiert werden, mit  Perl geht das immer. (z.B. unless, not, !~ ,...)

            Das ist wartbar und erspart den hier gezeigten kognitiven Overhead.

            Grüße
             Kurt

            1. Hello Kurt,

              Das ist wartbar und erspart den hier gezeigten kognitiven Overhead.

              hört sich interessant an. Muss ich unbedingt verfolgen!

              Ein harzliches Glückauf

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
          2. Hallo Uwe,

            Ich habs begriffen ...

            Kurzfassung:

            /^(?!Der Bau)/ muss ein LookAhead sein, weil es ab Zeilenanfang vorwärts schaut.

            Grüße
             Kurt

          3. Ich hoffe, ich habe das auf die Schnelle richtig und verständlich erklärt.

            Super, danke für deine ausführliche Beschreibung, das hilft mir wohl in Zukunft wenn ich wieder so was brauche weiter.

            Grüße, Chris