Stefan: Regex immer mal wieder

Hallo, Das mit den regulären Audrücken ist immer noch ein rotes Tuch für mich. Ich nutze sie und dennoch sind es oft die simpelsten darunter die mich zum verzweifeln bringen.

Das liegt aber auch daran, dass es wirklich keine gute Dokumentation, bzw gutes Tutorial darüber gibt.

Ist das leidliche Thema wie bei allem, wers verstanden hat, ist nicht mehr in der Lages es zu erklären, weil ihm viele Erklärungen dabei als selbstverständlich vorkommen.

Und, es geht vielen wie mir, also wenn jemand von euch (den Wissenden) in der Lage wäre ein Tutorial zu schreiben, das wirklich jeder Idiot versteht, wäre bestimmt ein Besucher Magnet. Habe wirklich heute mal wieder unzählige abgegrast und doch bin ich so klug als wie zuvor.

Aber jetzt zu meinem Problem:

Der Text : "sonne.html" "sonne2.html" "sonne3.html" "katze/sonne4.html" "sonnehtml.jpg" "sonne2.csv" "sonne3.txt" "katze/sonne4.php"

Dann will ich zb alles finden zwischen "" was "atz" drin hat. Das heisst die katzen würde ich bekommen.

Sollte doch einfach sein:

$reg = !! Erst mal delimiter festlegen

$reg = !""!  Dann zwischen " suchen

$reg =!""!is  egal ob gross oder klein und über mehrer zeilen

$reg = !".*"!is  Am Anfang darf irgendwas stehen

$reg = !".*[atz]"!is  Dann muss atz auftauchen

$reg = !".[atz]."!is  Am Ende wieder irgendwas

$reg = !".?[atz].?"!is     gierig abschalten (auch so eine sache die Keiner richtig erklärt)

Sooo heraus kommt: Array (     [0] => Array         (             [0] => "sonne.html"             [1] => "sonne2.html"             [2] => "sonne3.html"             [3] => "katze/sonne4.html"             [4] => "sonnehtml.jpg"             [5] => "sonne2.csv" "sonne3.txt"             [6] => "katze/sonne4.php"         )

)


Ich weiss aber nicht warum, und viel wichtiger wo ist mein Denkfehler ? Ich weiss das ist bestimmt einfach, aber genau das machts so schwierig.

Im übrigen suche ich eigentlich genau das Gegenteil, aber wenns einfach schon nicht klappt... $reg = !".?[^atz].?"!is

Gruss Stefan

Anhang Das folgende sind Kurznotizen die ich mir letzte Nacht gemacht hatte, als ich mir diese verd...ten Regexes wieder zu Gemüte geführt hatte.

Ist nur als Lesestoff und  Denkanstösse für Jemand gedacht dem es mit Regex's genau so geht wie mir. Hat also nichts mit meiner Frage zu tun. Steht auch viel Unsinn drin und somit tut es euch nicht an wenn Ihr mit regulären Ausdrücken klarkommt.

<p>------------------------------------</p> <h3>Einige Anregungen</h3> <h5>Beispielsatz: hansi hat eine realistische kur von steinen</h5>

<xmp> Beispiele <hr noshade size="1"> regex: ([a-z].+?)\s

Array (     [0] => Array         (             [0] => hansi             [1] => hat             [2] => eine             [3] => realistische             [4] => kur             [5] => von         )     [1] => Array         (             [0] => hansi             [1] => hat             [2] => eine             [3] => realistische             [4] => kur             [5] => von         ) )

############################

![a-z].+?\s!i

! Hier ist das leerzeichen mitvorhanden auch wenn man es jetzt nicht sieht

Array (     [0] => Array         (             [0] => hansi             [1] => hat             [2] => eine             [3] => realistische             [4] => kur             [5] => von         ) )

##########################

![a-z]+!i oder  !\w+!i

Das ist die kürzeste Form, dachte mir dabei buchstaben finden und mindestens einen weiteren buchstaben. Wenn U(gierig weg) nicht benutzt wird sucht er so lange bis kein buchstabe mehr kommt.

WICHTIG: Das kann man mit php auch leicht lösen zb. explode(' ',$array), aber: wenn nicht jede Trennung ein Leerzeichen ist was dann ? zb: hansi#hat&eine'realistische`kur # von steinen Hier spielt die Regex ihre Überlegenheit  voll aus, denn der ist es egal was als trenner steht hauptsache kein Buchstabe oder zahl.

Array (     [0] => Array         (             [0] => hansi             [1] => hat             [2] => eine             [3] => realistische             [4] => kur             [5] => von             [6] => steinen         ) )

wenn der string so wäre: hansi2hat&eine'realistische`kur 4# von steinen

Array (     [0] => Array         (             [0] => hansi2hat             [1] => eine             [2] => realistische             [3] => kur             [4] => 4             [5] => von             [6] => steinen         ) )

#########################

Jetzt mal ein paar Versuche. Ich verändere den Beispielsatz in: "Ein Gemälde ist meist eine realistische Interpretation"

Ich möchte aus dem Wort "realistische" das wort "ist" finden.

Das bedeutet erst mal eingrenzen, aber wie ?

also "ist" wird gesucht, was darf/kann/muss davor stehen ?

reg = ist = nur die Buchstaben "ist" [0] => Array         (             [0] => ist             [1] => ist             [2] => ist         )


Aha, also wirklich jedes "ist" wird gefunden.

Buchstaben davor ? ok also

reg = \wist = wenn es nur einer sein soll [0] => Array  (     [0] => eist     [1] => list  )

reg = \w+ = wenn es mehrere sein dürfen [0] => Array         (             [0] => meist             [1] => realist         )


Ja hier fehlt doch einer ? klar ist wird nicht gefunden, warum auch, existiert ja kein Buchstabe davor.

Hmm, jetzt will ich dieses einzelne ist aber auch haben, jedoch sollen bei den anderen wenn Buchstaben davor sind, diese auch gefunden werden. mal probieren:

reg = .+ist Oje, ganz schlecht der Gedanke: [0] => Array         (             [0] => Ein Gemälde ist meist eine realist         )

Was habe ich mir dabei gedacht ? Vor ist muss ein beliebiges Zeichen stehen, ach klar das ist ja schon falsch, kann/darf eines stehen also: Das liebe Fragezeichen anstatt plus. reg = .?ist  = "ist" gesucht davor darf ein buchstabe oder zahl stehen

und siehe da : [0] => Array         (             [0] =>  ist             [1] => eist             [2] => list         )


Dennoch, wieso klappts ? Hatte eigentlich erwartet, dass es nicht geht weils ja ein punkt ist und kein \w denn ein Leerzeichen ist doch auch ein zeichen oder nicht bzw. Warum dann überhaupt noch \w nehmen wenn der Punkt das gleiche macht ? Egal später. Nächster Versuch, mir gefällt nämlich nicht dass nur ein Buchstabe gefunden wird davor. Also mal testen:

.?ist  [0] => Array         (             [0] =>  ist             [1] => eist             [2] => list         ) -------------------------- \w?ist [0] => Array         (             [0] => Ein Gemälde ist             [1] =>  meist             [2] =>  eine realist         ) --------------------------- \w*?ist

Sogar mit U(nicht gierig) alles OK [0] => Array         (             [0] => ist             [1] => meist             [2] => realist         )

Dieses ist schon mal richtig aber warum ist das so ? Ich suche "ist". Davor darf ein Zeichen stehen \w (aber kein leerzeichen daher \w also und nicht ".") Aber nicht nur ein Zeichen sondern beliebig viele also \w. Andererseits darf aber auch keins enthalten sein, also noch ?, so kommen wir zu \w.? und natürlich zum suchbegriff "ist" also: \w*.?ist super es klappt ;-)

Grrr, klappt zwar aber nicht mit meiner Theorie. Das Fragezeichen kann ich mir sparen gleiches Ergebniss. Was hat es denn mit diesem Fragezeichen genau auf sich ?

Das Fragezeichen ? bedeutet in einem regulären Ausdruck, dass das Zeichen vor dem Fragezeichen Bestandteil der gefundenen Zeichenfolge sein darf, dass aber auch Zeichenfolgen ohne diese Zeichen gefunden werden.

Noch nicht ganz begriffen, aber später mehr dazu.


Beispielsatz nochmal geändert:

"Ein Gemälde ist m3eist eine realistische Interpretation"

Mal den Unterschied mit und ohne U(nicht gierig)

reg = !.+ist!iU

[0] => Array         (             [0] => Ein Gemälde ist             [1] =>  m3eist             [2] =>  eine realist         ) ----------------------- reg = !.+ist!i [0] => Array         (             [0] => Ein Gemälde ist m3eist eine realist         ) ---------------------------

Warum der Unterschied ? Kann nur vermuten ;-)

Ohne U:  zunächst mal das allerletzte "ist" finden, dann alle Zeichen davor egal wieviele und egal ob Leerzeichen oder nicht.

Mit U: Das erste Vorkommen von "ist" finden und alle Zeichen davor, dann übriggebliebenen string mal sehen ob noch ein "ist" vorkommt wieder alles davor ( was übrigblieb) zurück usw. bis kein ist mehr da ist.

Wenn es so ist, ärgere ich mich noch mehr über die zahllosen unverständlichen Tutorials zu Regex , denn wenn ich mal das phpmanual als Vorbild nehme, Stringfunktionen  "findet von bis" "findet ab erstes Vorkommen"  usw.

Ja kann man das denn hier nicht genau so einfach erklären ?

Mit   U  = letztes Vorkommen Ohne  U  = erstes Vorkommen

Und ein Punkt als Platzhalter "." kann auch ein Leerzeichen sein. Deshalb wenn Buchstaben/Zahlen davor sein sollen "\w" sonst ".". Wobei ich immer noch nicht "\b" verstehe. Na ja, später.

#######

</xmp>

<pre> Notiz: Der + Operator soll nicht greedy sein, das heißt, er soll nicht durchmarschieren bis zum letzten Punkt, sondern nur bis zum nächsten Punkt.

Bedeutet dass dass das Fragezeichen eine besondere Bedeutung hinter einem + bekommt ? Stop bei erster Funstelle. in dem fall eine domain web.de.blabla.blabla. .+?. = web. .+.  = web.de.blabla.blabla.

Das Zeichen \b Es wurde also lediglich da Dach ^ und das Dollar Zeichen durch eine word boundary \b ersetzt. Nun stellt sich die Frage, welches Zeichen durch die word boundary \b eigentlich dargestellt wird. Die Antwort ist: Gar keines. Eine word boundary ist immer dann gegeben, wenn das Zeichen links davon ein word element ist also zur Gruppe \w gehörig und rechts davon ein non word charakter Zeichen steht. Es muss also nicht unbedingt ein Leerzeichen das sein. Dies kann man der Tatsache entnehmen, dass die email Adresse in infos@infos24.de gefunden wird. Das Zeichen \b ist selber aber kein Zeichen und die regular expression wandert durch eine word boundary auch nicht weiter.

reg = .*\s(.+@)(.+?.\w+) $banane='Zu welcher Domain gehört eigentlich die email Adresse And3-res_Ehma.nn@web-berlin.de.Ich bin der Konfliktstoff. Noch schlimmer xy_hansi-berg.-test@dom-ain.de.uk.ca.museum wird es test3@yahoo.de bei mehreren Punkten.';

 [0] => Array         (             [0] => $banane='Zu welcher Domain gehört eigentlich die email Adresse And3-res_Ehma.nn@web-berlin.de.Ich bin der Konfliktstoff. Noch schlimmer xy_hansi-berg.-test@dom-ain.de.uk.ca.museum wird es test3@yahoo.de         )     [1] => Array         (             [0] => test3@         )     [2] => Array         (             [0] => yahoo.de         )

########################

Das beste von   http://www.infos24.de/phpe/handbuch/6_php_regular_expression.htm

\b\w[\w . -]+@\w[\w . -]+.[a-zA-Z]{2,4}\b

Eigene Variationen mit gleichem Ergebniss

\b[\w.-]+@\w[\w . -]+.[a-zA-Z]{2,4}\b

\b[\w.-]+@[\w.-]+.\w{2,4}\b

\b[\w.-]+@[\w.-]+.\w+\b

Funktioniert sehr gut weiss aber noch nicht warum genau  [0] => Array         (             [0] => And3-res_Ehma.nn@web-berlin.de.Ich             [1] => xy_hansi-berg.-test@dom-ain.de.uk.ca             [2] => test3@yahoo.de         )

#####################

Der Wildcard-Ausdruck .+, der "alles" bis zum Zeichen > holen soll, macht nämlich nicht beim nächsten > Stopp, sondern erst beim allerletzten. Durch das Anhängen des Fragezeichens, also durch Erweiterung auf .+?, beschränkt sich das Muster auf das Auffinden des nächsten >-Zeichens.

</pre>

  1. Hi!

    Dann will ich zb alles finden zwischen "" was "atz" drin hat.
    Das heisst die katzen würde ich bekommen.
    [...]

    $reg = !".*?[atz].*?"!is     gierig abschalten (auch so eine sache die Keiner richtig erklärt)

    Ich hab zwar genau 0 PHP-Kenntnisse, bin auch kein RegEx-Spezialist, bin aber zuversichtlich, dass sich dieses Problem einfach lösen lässt:

    [atz] heißt ja nicht „atz“, sondern „a“ oder „t“ oder „z“. Nachdem jede deiner Dateien auf „html“ endet, bekommst du alles.

    $reg = !".*?atz.*?"! sollte funktionieren.

    Gruß
    Bernhard

      1. Danke für deine Hilfe,

        Bitte.

        aber leider klappts nicht

        Tja, dann tuts mir Leid. Wie gesagt, ich hab von PHP gar keine Ahnung. Was auf jeden Fall mal falsch war, war „[atz]“ . Es sollte „atz“ oder „(atz)“ heißen.

        Gruß
        Bernhard

        1. Hallo Bernhard

          Was auf jeden Fall mal falsch war, war „[atz]“ . Es sollte „atz“ oder „(atz)“ heißen.

          Da hast du recht , das habe ich dann auch schon dazu gelernt.

          Die richtige Lösung kam von s.oliver:
          !"[^"]+atz[^"]*?"!is

          Wenngleich ich sie auch noch nicht ganz verstehe.

          Danke
          Stefan

  2. Servus,

    Das liegt aber auch daran, dass es wirklich keine
    gute Dokumentation, bzw gutes Tutorial darüber gibt.

    eine erstklassige Lektüre ist "Mastering Regular Expressions" von Jeffrey E. F. Friedl; erschienen ist der Band (aktuell in der zweiten Edition, wenn ich mich recht erinnere) bei O'Reilly.

    Dann will ich zb alles finden zwischen "" was "atz" drin hat.
    Das heisst die katzen würde ich bekommen.

    [...]

    $reg = !".*[atz]"!is  Dann muss atz auftauchen

    Nein, viel einfacher - '/"[^"]+atz[^"]*?"/is' findet den Abschnitt innerhalb des Strings, welcher mit '"' beginnt, 'atz' enthält und auf '"' endet, wobei innerhalb des Ergebnisses nur Zeichen liegen dürfen, die nicht '"' entsprechen (ganz einfach um das "kürzeste" Ergebnis zu bekommen). [^"] ist eine Charakterklasse, gekennzeichnet durch '[]', welche nur '"' nicht '^' enthält - das Caret sorgt dafür, dass alle aufgelisteten Zeichen innerhalb der Klasse nicht gefunden werden dürfen, wenn es direkt hinter der öffnenden Klammer steht.

    Dein Fehler war in diesem Moment, dass [atz] eine Charakterklasse ist, d.h. verbal: "Finde entweder ein 'a', ein 't' oder ein 'z'" und keine feste Zeichenkette - du willst aber 'atz' nur als feste Zeichenfolge finden, und musst sie deshalb auch (einfach) so schreiben.

    Noch ein Wort zur Quantifizierung in meinem Beispiel: '/"[^"]+atz[^"]*?"/is' - '[^"]+' vor 'atz' bedeutet, "mindestens ein (und so viel wie möglich) Zeichen, welches nicht '"' entspricht", so gewählt, da die Katze ohne das K recht arm dastehen würde (zumal, wenn es denn eine Tigerkatze oder ähnliches ist); das '[^"]*?' nach 'atz' steht für "kein oder so wenig wie möglich Zeichen, die nicht '"' entsprechen", da 'Katz' als Möglichkeit für mich nicht auszuschliessen ist.

    Grüsse

    1. Hallo Oliver,

      Erstmal Danke, das klappt.

      Deine Erklärung ( nimms mir nicht übel, denn du hast dir viel
      Mühe gegeben) ist sehr schwer zu verstehen. Das ist nämlich
      genau das was ich zuanfangst sagte, wer es einmal verstanden
      hat tut sich schwer es Unwissende zu vermitteln. Auch dein
      Buchtipp ist extrem kompliziert geschrieben.

      Mal sehen was ich denn nun verstanden habe.

      "[^"]+atz[^"]*?"

      Anführungszeichen am Anfang , OK (Verstanden)
      Dahinter darf keines sein  ,  NotOK (Nicht verstanden)

      Ist doch egal ob dahinter eines ist oder nicht, oder ?

      Nein stop du machst ein plus dahinter, also "muss" sogar
      eines dahinter gefunden werden, das ist dann der Moment wo ich gar nichts mehr verstehe.

      Aber ok lassen wir das erst mal aus.

      Dann soll atz gefunden werden und zwar nicht als einelne
      Buchstaben, ok da hatte ich wohl einen Fehler, aber das alleine wars
      nicht denn mit Berhards Anregung dahingehend klappts auch nicht.

      Hinter "atz" soll wieder kein " sein, NotOk versteh ich ja nicht
      weil sich ja sowieso alles zwischen 2 Anführungszeichen abspielt.

      Dann, das ganze soll x-mal aber nicht gierig gefunden werden,
      ok das ist mir wieder klar ;-)

      Gruss
      Stefan

      1. Servus,

        Deine Erklärung ( nimms mir nicht übel, denn du hast dir viel
        Mühe gegeben) ist sehr schwer zu verstehen. Das ist nämlich
        genau das was ich zuanfangst sagte, wer es einmal verstanden
        hat tut sich schwer es Unwissende zu vermitteln. Auch dein
        Buchtipp ist extrem kompliziert geschrieben.

        zur Ehrenrettung von Regulären Ausdrücken: das ist meine Schuld; ich mache vieles unnötig kompliziert, auch wenn ich das Gegenteil anstrebe. :/

        "[^"]+atz[^"]*?"

        Anführungszeichen am Anfang , OK (Verstanden)
        Dahinter darf keines sein  ,  NotOK (Nicht verstanden)

        [a] - finde ein 'a' - das ist klar.
        [a]+ - so viele davon, wie möglich

        [^a] - finde ein Zeichen, aber nicht 'a'; anders ausgedrückt: akzeptiere jedes Zeichen ausser 'a', aber nur ein Mal
        [^a]+ - so viele davon (das heisst: Zeichen, die nicht 'a' sind), wie möglich

        Ist doch egal ob dahinter eines ist oder nicht, oder ?

        Moment, dann habe ich Dich missverstanden. Wenn Du sagst zwischen "", dann heisst das normalerweise 'zwischen den zwei nächsten ""' - und logischerweise schliesst das ein '"' zwischen "" aus - '"bla " katze bla"' wäre also zum Beispiel nicht zulässig, '"bla katze bla"' schon.

        Nein stop du machst ein plus dahinter, also "muss" sogar
        eines dahinter gefunden werden, das ist dann der Moment wo ich gar nichts mehr verstehe.

        Nein, das Plus bezieht sich auf die Charakterklasse, und die verlangt eben 'Zeichen, die nicht '"' sind'.

        Dann soll atz gefunden werden und zwar nicht als einelne
        Buchstaben, ok da hatte ich wohl einen Fehler, aber das alleine wars
        nicht denn mit Berhards Anregung dahingehend klappts auch nicht.

        Sollte aber eigentlich funktionieren - mache mal ein vollständiges, zusammenhängendes Beispiel inklusive Text, Schleife/Bedingung und Audruck damit wir das in unseren Umgebungen mal testen können.

        Hinter "atz" soll wieder kein " sein, NotOk versteh ich ja nicht
        weil sich ja sowieso alles zwischen 2 Anführungszeichen abspielt.

        Das ist auch der Grund dafür, dass ich '[^"]' gewählt habe - so wird sicher gestellt, dass nur Zeichenketten erkannt werden, die im Zusammenhang stehen (alles anhand Deiner Beschreibung) - wenn zwischen den Paaren von Anführungszeichen weitere '"' stehen dürfen, müsste man den Ausdruck anpassen. So wie es ist, ist das die einfachste Art und Weise auszudrücken, dass nur gefunden werden soll, was 'atz' enthält, und zwischen den zwei nächsten (engsten, zusammengehörigen) Anführungszeichen steht.

        Ich hoffe das macht ein wenig mehr Sinn. ^^;

        Grüsse

        1. Hallo oliver,

          komme später nochmal auf den ganzen Text zu,
          aber du wolltest ein Beispiel, dass ich zwar schon in
          meiner Antwort zu Berhard hatte aber hier nochmal:

          http://regexp-evaluator.de/evaluator/9a4db7a243ec8e38c6c98dd09fabcf83/#ergebnis

          Sollte aber eigentlich funktionieren - mache mal ein vollständiges, zusammenhängendes Beispiel inklusive Text, Schleife/Bedingung und Audruck damit wir das in unseren Umgebungen mal testen können.

          1. Servus,

            Hier trifft zu, was ich Dir beschrieben habe: der erste Ausdruck ist gefrässig und sucht so viele Zeichen wie möglich, der zweite, weil er ein " zwischen "" ausschliesst, sucht nur was absolut ausreicht, um die Bedingung zu erfüllen - [^"]+ und [^"]*? in Aktion. ;)

            Teste das mal genau so:

            <?php

            // text, der durchsucht werden soll
            // nur etwas anders dargestellt
            // - zwischen '' sollten die " nicht maskiert werden
            // - um der Lesbarkeit des Beispiels willen in Fragmenten
            $subject =
                '"sonne.html"' . "\n" .
                '"sonne2.html"' . "\n" .
                '"sonne3.html"' . "\n" .
                '"katze/sonne4.html"' . "\n" .
                '"sonnehtml.jpg"' . "\n" .
                '"sonne2.csv"' . "\n" .
                '"sonne3.txt"' . "\n" .
                '"katze/sonne4.php"';

            // der reguläre ausdruck
            $pattern = '!".*?atz.*?"!is'; #$pattern = '!"[^"]+atz[^"]*?"!is';

            // regexp auswerten
            $result = preg_match_all( $pattern, $subject, $subpattern );

            // ergebnis ausgeben
            echo '<p>der verwendete reguläre ausdruck trifft auf den zu durchsuchenden text '.
               (($result) ? $result.' mal ' : 'nicht ').'zu.</p>';

            // unterausdrücke ausgeben
            echo '<pre>'.print_r($subpattern, true).'</pre>';

            #  ------------------------------------------- #  Ergebnis für $pattern = '!".*?atz.*?"!is'; #  ------------------------------------------- # #  der verwendete reguläre ausdruck trifft auf den zu durchsuchenden text 2 mal zu. # #  Array #  ( #      [0] => Array #          ( #              [0] => "sonne.html" #  "sonne2.html" #  "sonne3.html" #  "katze/sonne4.html" #              [1] => "sonnehtml.jpg" #  "sonne2.csv" #  "sonne3.txt" #  "katze/sonne4.php" #          ) #  )

            #  ------------------------------------------- #  Ergebnis für $pattern = '!"[^"]+atz[^"]*?"!is'; #  ------------------------------------------- # #  der verwendete reguläre ausdruck trifft auf den zu durchsuchenden text 2 mal zu. # #  Array #  ( #      [0] => Array #          ( #              [0] => "katze/sonne4.html" #              [1] => "katze/sonne4.php" #          ) #  )

            ?>

            Grüsse

            1. Hello again ;-)

              #  Ergebnis für $pattern = '!"[^"]+atz[^"]*?"!is';

              Ja ich sagte ja schon, dass dein Ausdruck klappt.
              Nur verstehe ich nicht warum nur so und nicht anders.

              Probieren wirs mal anders:
              (vielleicht frage ich ja auch zu kompliziert)

              "hans1@web.de"
              "hans2@web.de"
              "hans3@web.de"
              "hans4@web.de"

              Das ist der Text , beachten dabei die Zeilenumbrüche.
              Ich denke jetzt wenn ich jeweils von einem "bis zum nächsten
              suchen möchte, wäre das so zu machen:
              " = Damit fängt das an
              " = damit hört es auf

              Also !""! Jetzt steht aber noch nichts zwischen den beiden
              ". Also darum habe ich den Fall gewählt dazwischen ist ein
              @.

              Also !"@"!

              Kann aber nicht gefunden werden, weil das ja so bedeutet
              Klammeraffe muss direakt neben Anführungszeichen sein.
              Unbekannte zeichen unbekannter länge davor und dahinter.

              Also
              !".*@.*"!is
              Nö, zu gefrässig, aber das lässt sich ja ändern.

              !".*?@.*?"!is

              Ausgabe:
              Array
              (
                  [0] => Array
                      (
                          [0] => "hans1@web.de"
                          [1] => "hans2@web.de"
                          [2] => "hans3@web.de"
                          [3] => "hans4@web.de"
                      )

              )

              ---------------------------------------
              Jetzt das Gemeine daran. Ich erhalte das Array wie ich es mir vorstelle und denke dann stimmt meine Theorie beim zusammenbasteln.

              Aber das tut sie natürlich nicht.

              Du benutzt da einen anderen Weg, der aus irgendeinem Grund
              hinter dem 1. " ein 2." ausschliesst und damit klappts
              aber ich weiss nicht warum, denn

              Ich will doch suchen zwischen 2 " also

              !"erstmal egal was hier steht"!

              Vielleicht verstehe ich es wenn du deinen Ausdruck so umstellen
              kannst dass es auch geht wenn du nicht das [^"] drin hast.
              denninnherhalb der Emailadressen taucht das ja auch nicht auf erst
              am Ende wo es ja auch sein soll.

              --------------------------------------
              Langsam wirds für dich bestimmt frustrierend, aber genau
              solche Sachen fehlen in den ganzen Dokus.

              Gruss
              Stefan

              1. Servus,

                !".*?@.*?"!is
                [...]
                Jetzt das Gemeine daran. Ich erhalte das Array wie ich es mir vorstelle und denke dann stimmt meine Theorie beim zusammenbasteln.

                Aber das tut sie natürlich nicht.

                doch, soweit ich das sehen kann, hast Du das alles richtig erklärt. Du berücksichtigst aber nicht die Arbeitsweise der Regex Engine.

                Du benutzt da einen anderen Weg, der aus irgendeinem Grund
                hinter dem 1. " ein 2." ausschliesst und damit klappts
                aber ich weiss nicht warum, denn

                Ich will doch suchen zwischen 2 " also

                !"erstmal egal was hier steht"!

                Was jetzt folgt ist meine ad-hoc Deutung dieser Ausdrücke - nimm das um Gottes Willen nicht als die exakte Arbeitsweise der RegEx Engine. Für Derartiges bitte das Buch von Friedl zu Rate ziehen.

                --------------------------
                /".*?@.*?"/ Interpretation
                --------------------------

                Muster: /".*?@.*?"/
                Text: '"invalide"email@adres.se"mit anhang"'

                • Implizit: (lies einen Text ein, suche dieses Muster)
                • Implizit: (fange beim ersten Zeichen an)

                • "   -> finde das erste ", dessen Du habhaft werden kannst
                    gefunden: '"'
                • .*? -> finde so wenig wie möglich Zeichen danach (egal welche, also auch "), bis die nächste Bedingung erfüllt ist(!)
                    gefunden: '"invalide"email'
                • @   -> finde ein @
                    gefunden: '"invalide"email@'

                Soweit klar? Das Muster sagt nichts in der Art "Finde '@', dann gehe zurück im Text und finde so wenig andere Zeichen zwischen '@' und '"' wie möglich", sondern einfach nur das, nichts anderes. Der Ausdruck startet am Anfang des Textes und sucht von dort aus so wenig Zeichen wie möglich, bis die restlichen Bedingungen erfüllt sind - falls sie erfüllt werden können.

                • .*? -> finde so wenig wie möglich Zeichen danach (egal welche), bis die nächste Bedingung erfüllt ist
                    gefunden: '"invalide"email@adres.se'
                • "   -> finde ein "
                    gefunden: '"invalide"email@adres.se"'

                Damit hat die Engine ihr erstes Ergebnis gefunden und sucht gegebenenfalls - startend beim nächsten Zeichen - nach einem neuen Treffer.

                ------------------------------
                /"[^"]+@[^"]+"/ Interpretation
                ------------------------------

                Muster: /"[^"]+@[^"]+"/
                Text: '"invalide"email@adres.se"mit anhang"'

                • Implizit: (lies einen Text ein, suche dieses Muster)
                • Implizit: (fange beim ersten Zeichen an)

                • "      -> finde das erste ", dessen Du habhaft werden kannst
                    gefunden: '"'
                • [^"]+@ -> finde alle Zeichen ausser ", bis ein @ gefunden wird
                    gefunden: '"email@'
                              , da '"invalide"email@' die Bedingung nicht erfüllt

                Das Muster muss vollständig gefunden werden. Die Engine versucht es zuerst mit '"invalide', entdeckt dann '"', welches aber ausdrücklich vor '@' nicht wieder gefunden werden soll, und muss deshalb diesen ersten Versuch abbrechen. Sie setzt dann bei '"' zwischen 'invalide' und 'email' zu einer neuen Suche an; bei dem Zeichen also, vor dem der erste Versuch soeben gescheitert ist. Das wird so lange fortgeführt, bis entweder eine Bedingung nicht erfüllt wird, oder eine Entsprechung des gesamten Musters lokalisiert ist.

                • [^"]+" -> finde alle Zeichen ausser ", bis sich ein " nicht mehr vermeiden lässt
                    gefunden: '"email@adres.se"'

                ------------------------------

                Vielleicht verstehe ich es wenn du deinen Ausdruck so umstellen
                kannst dass es auch geht wenn du nicht das [^"] drin hast.
                denninnherhalb der Emailadressen taucht das ja auch nicht auf erst
                am Ende wo es ja auch sein soll.

                Eine andere Möglichkeit: /\b\w[-.\w]*@[-a-z0-9]+(?:[-a-z0-9]+)*.[a-z.]+[a-z]\b/

                Während das vorherige Muster durch die [^"] Charakterklasse zusammengehalten wird, sorgen hier die Wortbegrenzer \b an Anfang und Ende, die Vermeidung von Leerzeichen und die Charakterklassen dafür, dass (wenn alles gut geht) das Muster nur die Email-Adresse trifft. Dies ist übrigens ein etwas abgewandeltes Beispiel von Friedl.

                Es ist alles kein Problem, so lange die gesuchten Strings gut abgrenzbar sind. Problematisch wird es eben, wenn beispielsweise in einem Fliesstext Begrenzungszeichen auch in anderen Zusammenhängen auftauchen, oder Namenskonventionen nicht strikt eingehalten werden. Ein regulärer Ausdruck sollte so gewählt werden, dass er strikt genug ist, um alle konformen Ergebnisse zu erfassen, und nachsichtig genug, um so viele Abweichler oder potentielle Kandidaten wie möglich zu treffen.

                Grüsse

                1. Soweit klar? Das Muster sagt nichts in der Art "Finde '@', dann gehe zurück im Text und finde so wenig andere Zeichen zwischen '@' und '"' wie möglich", sondern einfach nur das, nichts anderes. Der Ausdruck startet am Anfang des Textes und sucht von dort aus so wenig Zeichen wie möglich, bis die restlichen Bedingungen erfüllt sind - falls sie erfüllt werden können.

                  Das ist für mich schon mal ein Quantensprung, denn bisher
                  dachte ich so wäre es:

                  Anfang: ergänze links <- suche ein Zeichen -> ergänze rechts :Ende

                  Gut erklärt, danke.

                  Nun verstehe ich also:

                  "["]./?[^"]"

                  -------------------------------------

                  Na mit diesem neuen Wissen auf zum Test:

                  "sonne.html""sonne2.html" "sonnehtmlx.jpg" "sonne3.html""katze/sonne4.html""sonnehtml.jpg"   "sonne2.csv" "sonne3.txt" "katze/sonne4.php"

                  Daraus möchte ich alles haben was innerhalb " und den
                  begriff "html" enthält.
                  Also:
                  !"[^"]*?html[^"]*?"!is      Richtig so ?

                  Ausgabe:
                  Array
                  (
                      [0] => Array
                          (
                              [0] => "sonne.html"
                              [1] => "sonne2.html"
                              [2] => "sonnehtmlx.jpg"
                              [3] => "sonne3.html"
                              [4] => "katze/sonne4.html"
                              [5] => "sonnehtml.jpg"
                          )

                  )

                  -------------------------------------

                  Scheint zu klappen, dann trau ich mich doch glatt mal weiter.
                  Jetzt das gleich aber ich will alles zwischen " haben was nicht
                  den Begriff "html" enthält.

                  Also:
                  !"[^"]*?^html*[^"]*?"!is    Das klappt dann aber wieder nicht ;-(

                  Das ist immer so mit den Regex, kaum denkt man es geht voran
                  bekommt man prompt den Dämpfer und die selbstgedachte Logik
                  ist dahin.

                  PREG_MATCH_ALL() Es wurde keine Übereinstimmumg gefunden

                  Gruss
                  Stefan

                  ps. Deine Erklärung war sehr einleuchtend, zumindest begreife
                  ich jetzt wieder ein bisschen mehr.

                  1. Servus,

                    Scheint zu klappen, dann trau ich mich doch glatt mal weiter.
                    Jetzt das gleich aber ich will alles zwischen " haben was nicht
                    den Begriff "html" enthält.

                    Also:
                    !"[^"]*?^html*[^"]*?"!is    Das klappt dann aber wieder nicht ;-(

                    Das Caret (^) hat in Regulären Ausdrücken zwei Bedeutungen:
                    1. Als Indikator für den Anfang des Strings oder den Zeilenanfang nach einem Umbruch - wohl das häufigere Anwendungsgebiet
                    2. Als Negationszeichen innerhalb einer Charakterklasse (und nur da)

                    In Deinem Beispiel versuchst Du also möglicherweise, einen String zu finden, bei dem vor 'html' ein Zeilenumbruch stattfindet. ;-)

                    Grundsätzlich könntest Du natürlich einfach zwei Bedingungen verknüpfen, wobei Du testest, ob die Substrings a) der richtigen Form entsprechen und b) einen bestimmten String nicht enthalten ( preg_match( '/^"[^"]*?[^" ]+[^"]*?"$/i'... && !preg_match( '/html/'... so in der Art ) - ich nehme aber mal an, das ist jetzt nicht Sinn und Zweck der Übung.

                    Eine andere Möglichkeit wäre, einen negativen Lookahead zu verwenden; dabei prüft die Engine sozusagen, ob vor der jetzigen Position des internen Zeigers eine bestimmte Zeichenkette nicht gefunden werden kann, ohne diese Kette aber in das Ergebnis mit aufzunehmen (normalerweise würde die Engine jedes Zeichen was dem Suchmuster entspricht 'fressen', d.h. für das letztendliche Ergebnis festhalten). Dieses spezielle Verhalten hat den Vorteil, das wir, ohne irgendetwas in Speicher oder Resultset zu kopieren, erst einmal testen können, ob eine Kette vorhanden ist; ist sie vorhanden, erzeugt die negative Lookahead assertion einen Fehler und die Engine sucht sich den nächsten Kandidaten.

                    Ich schlage vor, Du liest Dir erst mal in der Quelle Deiner Wahl etwas zu Lookahead und Lookbehind assertions durch, falls das noch nicht viel Sinn gemacht hat.

                    In Deinem speziellen Beispiel (Sonne und html), könnte der Ausdruck in etwa so aussehen: /"((?![^"]*html[^"]*)[^"]*[^" ][^"]*)"/.

                    Grüsse

                    1. Hallo Oliver,
                      hatte schon gehofft, dass du dich meldest ;-)

                      In Deinem speziellen Beispiel (Sonne und html), könnte der Ausdruck in etwa so aussehen: /"((?![^"]*html[^"]*)[^"]*[^" ][^"]*)"/.

                      Nicht zu fassen,  habe den ganzen tag rumprobiert.
                      Und mich auch mit den Assertions beschäftigt tonnen
                      an Internetseiten gewältzt und kam nicht weiter.

                      Dabei war ich doch schon nah dran: "[^"]*?(?!html)[^"]*?"
                      Wäre nie drauf gekommen das ?! noch vor [^"] zu setzen.
                      Versteh es auch jetzt noch nicht.

                      Aber was ich durch deine Erklärung verstanden habe ist wohl,
                      dass die Negierung ^ nur bei einzelnen Zeichen oder
                      Zeichengruppen oder Kurzschreibweisen dergleichen
                      funktioniert, nicht aber bei Wörtern , richtig ?

                      Ich schlage vor, Du liest Dir erst mal in der Quelle Deiner Wahl etwas zu Lookahead und Lookbehind assertions durch, falls das noch nicht viel Sinn gemacht hat.

                      Ja das habe ich getan, aber leider.... nicht ganz begriffen.
                      bzw. Eigentlich ist das Prinzip ja einfach mit "true or not true"
                      zu  verstehen. Allerdings warum das wo genau und wie eingeklammert
                      sein müsste das ist mir nicht klar.

                      Übrigens, bei deiner Hilfe hierbei:
                      Jetzt sehe ich aber auch wie ein gutes Tutorial aufgebaut
                      sein müsste. Nicht wie üblich . Ein Wissender erklärt
                      die Anderen hören zu. Sondern eindeutig als Dialog mit
                      einem Nichtwissenden. Aber auch nicht mehr Personen dann
                      wirds forenmässig und der Faden geht verloren.

                      Das ganze nach einem  ziemlich strikten formellen Muster,
                      was eine gewisse Übersichtlichkeit erlaubt.

                      Besteht die Möglichkeit, dass Du mal Zeit und Interesse an so
                      einem Tutorialaufbau in Zukunft hättest ?

                      Gruss
                      Stefan

                      1. Servus,

                        Nicht zu fassen,  habe den ganzen tag rumprobiert.
                        Und mich auch mit den Assertions beschäftigt tonnen
                        an Internetseiten gewältzt und kam nicht weiter.

                        ich musste mir dieses Prinzip auch noch mal verdeutlichen, damit ich hier keinen Mist schreibe. :)

                        Aber was ich durch deine Erklärung verstanden habe ist wohl,
                        dass die Negierung ^ nur bei einzelnen Zeichen oder
                        Zeichengruppen oder Kurzschreibweisen dergleichen
                        funktioniert, nicht aber bei Wörtern , richtig ?

                        Nur bei Charakterklassen, d.h. nur bei einem einzelnen Zeichen. [^a]+ bedeutet nicht 'finde jedweden Substring ausser "aaaa..."', sondern 'finde jedwedes einzelne Zeichen ausser "a", finde jedwedes einzelne Zeichen ausser "a", finde jedwedes einzelne Zeichen ausser "a", ...'.

                        [Lookarounds nachlesen]

                        Ja das habe ich getan, aber leider.... nicht ganz begriffen.
                        bzw. Eigentlich ist das Prinzip ja einfach mit "true or not true"
                        zu  verstehen. Allerdings warum das wo genau und wie eingeklammert
                        sein müsste das ist mir nicht klar.

                        Ich werde dazu wenn ich mehr Zeit habe noch ein paar Zeilen schreiben, grundsätzlich hilft es Lookarounds eher als Positionsabfrage denn als Zeichenabfrage zu sehen. "Trifft auf die jetzige Position im String der folgende Ausdruck zu?"

                        Besteht die Möglichkeit, dass Du mal Zeit und Interesse an so
                        einem Tutorialaufbau in Zukunft hättest ?

                        Du solltest Dich vielleicht eher fragen, ob ich dafür qualifiziert bin. Das ist kein 'Nein' zu Deiner Frage. ;-)

                        Grüsse

                      2. Servus,

                        also, noch mal zu den Lookarounds.

                        Es gibt zwei Lookaheads, welche sich nach rechts(*) orientieren:
                        positiv - (?=bla)
                        negativ - (?!bla)

                        und zwei Lookbehinds, welche sich nach links(*) orientieren
                        positiv - (?<=bla)
                        negativ - (?<!bla)

                        (*) entsprechend unserem Schriftsystem ("von links oben nach rechts
                        unten"), orientiert sich der "Blick voraus" nach rechts und der
                        "Blick zurück" nach links

                        Dabei wird von den Lookarounds erwartet, dass die enthaltene Zeichenkette
                        (bla) in der jeweiligen Richtung direkt angrenzend an den Lookaround vorkommt
                        (positiv) oder nicht vorkommt (negativ). Wird die Erwartung erfüllt, geben
                        sie grünes Licht für den aktuellen Suchvorgang. Bitte beachten: Lookbehinds
                        dürfen im Gegensatz zu Lookaheads nur auf Zeichenketten mit fester Länge
                        testen - die Benutzung von Quantifizierern wie .*, .*?, .+, .{x,} etc. ist
                        deshalb beispielsweise nicht gestattet. Das ist auch ein Grund, weshalb wir
                        für unsere Negation lediglich den Lookahead benutzen.

                        So, was macht eigentlich unser Ausdruck /"((?![^"]*html[^"]*)[^"]*[^" ][^"]*)"/?
                        Schlüsseln wir das Ganze mal auf - die Zeilen 02 bis 06 gehören zum Lookahead.

                        "                #01 finde das Zeichen "
                            (?!          #02 Schaue voraus; stelle fest, ob die folgende Kette nicht vorkommt
                                [^"]*    #03   jedwedes Zeichen ausser " [1]
                                html     #04   die Zeichenkette html
                                [^"]*    #05   jedwedes Zeichen ausser " [1]
                            )            #06 Ende des Ausblicks
                            [^"]*        #07 finde jedwedes Zeichen ausser " [1]
                            [^" ]        #08 finde ein Zeichen, welches weder ein '"' noch ein ' ' ist [2]
                            [^"]*        #09 finde jedwedes Zeichen ausser " [1]
                        "                #10 finde das Zeichen "

                        [1] Findet so viele Charaktere wie möglich (0 bis n)
                        [2] Damit soll ein leeres Ergebnis vermieden werden, bzw eines,
                            welches nur Leerzeichen enthält.

                        Die RegEx-Engine setzt in Zeile 02 zum Ausblick nach rechts an, und prüft,
                        ob der gesamte String den wir erfassen wollen, die Zeichenkette html _an
                        einer beliebigen Stelle_ enthält. Wir suchen sozusagen zwei Mal nach der
                        gesamten Zeichenkette, die für uns interessant ist, einmal im Lookahead
                        und einmal in unserer eigentlichen Zeichensuche. Entsprechend der Zeilen
                        03 und 05 darf jede beliebige Anzahl von Zeichen ausser " vor und nach
                        dem html auftreten - "html_bla" ist von unserem Muster also ebenso
                        betroffen, wie "bla_html_bla", "html_bla" und "html". Du kannst für Dich
                        mal testen, wie Du den Lookahead umstellen müsstest, damit nur jeweils
                        eine dieser Möglichkeiten ausgeschlossen wird.

                        Sobald die Engine den Lookahead mit Zeile 06 komplett angewandt hat,
                        wird das Ergebnis ermittelt - wurde html an keiner beliebigen Stelle
                        des Strings gefunden, ist das negative Lookahead erfolgreich. Nur im
                        Erfolgsfall wird jetzt ab Zeile 07 unser Suchmuster erneut auf den
                        String angewandt, und die einzelnen Zeichen werden von der Engine
                        "gefressen" (d.h. intern in das Ergebnis einbezogen, wobei der Zeiger
                        jeweils auf die Position nach dem gefressenen Zeichen wandert).

                        Wenn wir wie hier auf das Nichtvorhandensein an einer beliebigen Stelle
                        testen, muss der Lookahead an den Anfang des Suchmusters, da der Inhalt
                        des Lookaheads ebenfalls das gesamte Suchmuster testet (ansonsten geht
                        die Wirkung des Lookaheads verloren) - sobald wir irgendeine Zeichenkette
                        vor dem Lookahead suchen lassen, ist die Kontrollwirkung des Lookaheads
                        ausgehebelt, welche in unserem Beispiel ja lautet: "Starte die Ergebnis-
                        findung nur, wenn ich vorher html nicht finden konnte".

                        Grüsse

                        1. Hallo Oliver,
                          Du gibst Dir wirklich viel Mühe und was deine
                          Qualifikation betrifft, bist du sogar überqualifiziert.

                          Daher mein Vorschlag mit dem Tutorial.
                          Denn auch jetzt verstehe ich nicht alles,
                          müsste in kleineren Schritten anhand von
                          Kurzbeispielen dialogisiert werden.

                          Ich gebe dir mal eine Email von mir,
                          bevor dass hier alles im Nirwana des Archivs wandert ;-)

                          selfregex-oliver@yahoo.de

                          Wäre nett wenn Du dich meldest.

                          Gruss
                          Stefan

  3. 'Nabend Stefan.

    Das liegt aber auch daran, dass es wirklich keine
    gute Dokumentation, bzw gutes Tutorial darüber gibt.

    Das sehe ich anders. Die Suchmaschinen fördern etliche Tutorials und (Kurz-)Referenzen zutage. Die PHP-Doku widmet dem Thema mehrere Seiten und gibt auch Beispiele. Was genau ist das Problem mit deinen bisherigen Funden?

    Aber jetzt zu meinem Problem:

    Der Text :
    "sonne.html"
    "sonne2.html"
    ...

    Da du zum Thema RegEx an anderer Stelle im Thread ja bereits verarztet wirst, folgender Vorschlag als Alternative:

    Benutzen einfach explode() zum Aufteilen der Zeilen und anschließend strpos() zum Suchen der Zeichenkette "atz" in jeder Zeile. Falls der obige Text zeilenweise in einer Datei steht, kannst du ihn auch direkt mit file() in ein Array einlesen anstatt explode() auf den kompletten String anzuwenden.

    --
    Once is a mistake, twice is jazz.

    1. Hallo Blaubart.

      Das liegt aber auch daran, dass es wirklich keine
      gute Dokumentation, bzw gutes Tutorial darüber gibt.

      Das sehe ich anders. Die Suchmaschinen fördern etliche Tutorials und (Kurz-)Referenzen zutage.

      Mein ständiger Favorit, da simpel, übersichtlich und einfach nützlich, ist der PCRE–Evaluator.

      […] folgender Vorschlag als Alternative:

      Benutzen einfach explode() zum Aufteilen der Zeilen und anschließend strpos() zum Suchen der Zeichenkette "atz" in jeder Zeile. […]

      Hierbei finde ich immer wieder interessant, wie viel doch nur allein mit den Zeichenkettenfunktionen umsetzbar ist. In Kombination miteinander sind sie oft ebenso mächtig wie ein regulärer Ausdruck und hin und wieder sogar noch besser. Von einem möglichen Performancegewinn ganz zu schweigen.

      <del>Reguläre Ausdrucke sind was für Faule.</del><ins>Einziger „Nachteil“: sie erfordern oft ein wenig mehr Nachdenkarbeit</ins>

      Einen schönen Montag noch.

      Gruß, Ashura

      --
      sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
      „It is required that HTML be a common language between all platforms. This implies no device-specific markup, or anything which requires control over fonts or colors, for example. This is in keeping with the SGML ideal.“
      [HTML Design Constraints: Logical Markup]

      1. Hallo Ashura

        Mein ständiger Favorit, da simpel, übersichtlich und einfach nützlich, ist der PCRE–Evaluator.

        Ja die Seit ist gut zum ausprobieren, aber zum lernen ?
        Nicht wirklich.

        In dieser Hinsicht finde ich am Besten
        ( Obwohl mich nicht wirklich weiterbringt aber immerhin Grundsätzliches vermittelt)

        http://www.infos24.de/phpe/handbuch/6_php_regular_expression.htm

        oder

        http://www.regenechsen.de/phpwcms/index.php?regex_dt_tb

        Zum Thema "lieber stringfunktionen nutzen habe ich Blaubart schin geantwortet)

        Warum tun sich viele so schwer Regex's in Dokus zu lernen ?
        Weil im Gegensatz zu vielem anderen Lernstoff (php,asp, c++)
        Regex's augenscheinlich logisches auf einmal adabsurdum führen.

        Oder anders Bei PHP gibts für mich nur schwartz oder  weiss
        an oder aus, bei den reg's denke ich muss klappen aber dann kommen
        vielen wenn aber /doch \muss*könnte?wieso. Ich finde da einfach noch
        nicht die Logik, die natürlich vorhanden sein muss.

        Stefan

        1. Hallo Stefan.

          Mein ständiger Favorit, da simpel, übersichtlich und einfach nützlich, ist der PCRE–Evaluator.

          Ja die Seit ist gut zum ausprobieren, aber zum lernen ?
          Nicht wirklich.

          Hm, das sehe ich genau anders herum. Ich hatte die Site schon seit einiger Zeit nicht mehr aufgerufen, weshalb ich erst vor kurzem die komplette Überarbeitung der alten Fassung bemerkte. Mittlerweile ist das Tutorial sehr ausführlich und meiner Meinung nach auch leicht verständlich.

          Warum tun sich viele so schwer Regex's in Dokus zu lernen ?
          Weil im Gegensatz zu vielem anderen Lernstoff (php,asp, c++)
          Regex's augenscheinlich logisches auf einmal adabsurdum führen.

          Dabei sind reguläre Ausdrücke in sich doch auch logisch aufgebaut. Beherrscht man erst einmal die grundlegende Syntax, sind die nächsten Schritte weniger aufwendig.

          Einen schönen Montag noch.

          Gruß, Ashura

          --
          sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
          „It is required that HTML be a common language between all platforms. This implies no device-specific markup, or anything which requires control over fonts or colors, for example. This is in keeping with the SGML ideal.“
          [HTML Design Constraints: Logical Markup]

    2. Hallo Blaubart

      Das sehe ich anders. Die Suchmaschinen fördern etliche Tutorials und (Kurz-)Referenzen zutage. Die PHP-Doku widmet dem Thema mehrere Seiten und gibt auch Beispiele. Was genau ist das Problem mit deinen bisherigen Funden?

      Was meinst du jetzt mit Funden ?
      Bezüglich Literatur oder mein Regex Ergebniss ?
      Was die ganzen Tutorials/Dokus angeht , nein die sind
      nicht gut, sonst hätten nicht so viele Leute Probleme mit
      regulären Ausdrücken , obwohl die gleichen Leute
      es schaffen hochkomplexe Scripte/Software oder anderes
      zu schreiben.

      Benutzen einfach explode() zum Aufteilen der Zeilen und anschließend strpos() zum Suchen der Zeichenkette "atz" in jeder Zeile. Falls der obige Text zeilenweise in einer Datei steht, kannst du ihn auch direkt mit file() in ein Array einlesen anstatt explode() auf den kompletten String anzuwenden.

      Nein Blaubart, die Zeilen waren nur ein Beispiel dessen
      was ich wirklich suche und was wesentlicher komplexer ist.

      Mit php kann ich klar alles was ich auch mit regulären
      Ausdrücken kann, aber eben wesentlich script- und schleifenlastiger.

      Und eben weil ich jetzt endlich mal mehr mit dieses Regex's machen
      will muss ich mich durch den Anfangswall durchwursteln um dann
      endlich auch die komplizierte Literatur zu verstehen, um dann
      letztendlich hinterher auch nicht mehr zu verstehen wieso
      ich so einfache sachen nicht verstanden habe ;-)

      Gruss
      Stefan

      1. 'Nabend.

        Was genau ist das Problem mit deinen bisherigen Funden?

        Was meinst du jetzt mit Funden ?
        Bezüglich Literatur oder mein Regex Ergebniss ?

        Ersteres. Du fällst ein so pauschales Urteil über alle Dokumentationen und Tutorials zum Thema RegExp, das mich einfach interessiert, was du an denen, die du gelesen hast, nicht gut findest.

        Was die ganzen Tutorials/Dokus angeht , nein die sind
        nicht gut, sonst hätten nicht so viele Leute Probleme mit
        regulären Ausdrücken , obwohl die gleichen Leute
        es schaffen hochkomplexe Scripte/Software oder anderes
        zu schreiben.

        Ist das tatsächlich so? Wer sind diese Leute, die so "hochkomplexe Software" schreiben, an regulären Ausdrücken jedoch verzweifeln?

        Nein Blaubart, die Zeilen waren nur ein Beispiel dessen
        was ich wirklich suche und was wesentlicher komplexer ist.

        Ok, das konnte ich nicht wissen. Wie gesagt, es war ein Lösungsvorschlag zu dem, was du hier als "dein Problem" vorgestellt hast.

        Mit php kann ich klar alles was ich auch mit regulären
        Ausdrücken kann, aber eben wesentlich script- und schleifenlastiger.

        Was nicht immer ein Nachteil ist – sowohl in Hinblick auf Performance als auch Wartbarkeit und Übersichtlichkeit.

        --
        Once is a mistake, twice is jazz.

        1. hello again,

          was du an denen, die du gelesen hast, nicht gut findest.

          Es fehlen oft nach guten Einleitungserklärungen genügend
          konkrete (vor allem negative )Beispiel um zumindest
          Autodidakten eine Lernmöglichkeit zu geben.

          Es ist eben so: Du willst etwas lernen und hast viele
          Fragen, die Experten gar nicht mehr als mögliche Frage
          ansehen. Würde ich heute ein Buch über PHP schreiben,
          fiele es mir auch schwer mich an die vielen Fragen
          zu erinnern die ich heute als selbsterklärend abtue.

          Ist das tatsächlich so? Wer sind diese Leute, die so "hochkomplexe Software" schreiben, an regulären Ausdrücken jedoch verzweifeln?

          Da gibt es unzählige Beispiele wenn man mal den Background von
          so manchem Fragesteller in den Foren ableuchtet.
          onthefly mal ganz schnell gegoogelt
          http://forum.de.selfhtml.org/archiv/1999/2/t2109/
          Kann zwar seinen Background nicht so schnell durchschauen,
          aber bestimmt kein Anfänger.

          Was nicht immer ein Nachteil ist – sowohl in Hinblick auf Performance als auch Wartbarkeit und Übersichtlichkeit.

          Nehmen wir ein einfaches Beispiel:
          $x = "hansi#hat&eine'realistische`kur # von steinen";

          Finde mit php nur die Worte:
          Hier hilft kein explode. Mann muss jedes Zeichen durchlaufen
          und prüfen ob es ein Buchstabe ist, dass dann alles noch verpacken.

          In regex: !\w+!i   , schon haben wir ein Array mit allen Wörtern.

          1. Hallo Stefan.

            Es fehlen oft nach guten Einleitungserklärungen genügend
            konkrete (vor allem negative )Beispiel um zumindest
            Autodidakten eine Lernmöglichkeit zu geben.

            In diesem Fall möchte ich dir nochmals das bereits von Ashura angesprochene Tutorial auf www.regexp-evaluator.de ans Herz legen.

            http://forum.de.selfhtml.org/archiv/1999/2/t2109/
            Kann zwar seinen Background nicht so schnell durchschauen, ...

            Eben. Und das dürfte nicht nur bei diesem Beispiel der Fall sein.

            ... aber bestimmt kein Anfänger.

            *Heute* sicher nicht mehr. Keine Ahnung, wie das vor 7 Jahren aussah... Besonders in Sachen RegEx. Wir können Cheatah ja mal fragen. ;)

            Davon mal abgesehen schien er keine grundlegenden Probleme beim Verständnis von regulären Ausdrücken zu haben, wie du sie offenbar hast. Er war vielmehr auf der Suche nach einer Lösung für eine Problemstellung, die er mit regulären Ausdrücken angehen wollte. Ich sehe darin keinen großen Unterschied zu jemandem, der im Forum eine Frage zu SQL-Queries stellt. Daraus folgert auch niemand, daß "viele Leute" Probleme mit SQL haben, die sonst in der Lage sind "hochkomplexe Software zu schreiben". Oder doch? ;)

            Was nicht immer ein Nachteil ist – sowohl in Hinblick auf Performance als auch Wartbarkeit und Übersichtlichkeit.

            »»

            »»

            Nehmen wir ein einfaches Beispiel:
            $x = "hansi#hat&eine'realistische`kur # von steinen";

            »»

            Finde mit php nur die Worte

            Ich habe nirgends behauptet, daß alternative Herangehensweisen (und schon gar nicht explode) *in jedem Fall* die bessere/kürzere/performantere Lösung sind im Gegensatz zu regulären Ausdrücken. Wozu also dieses Beispiel?

            Zum gekonnten Umgang mit regulären Ausdrücken zählt für mich auch, sowohl deren geeignete Einsatzgebiete als auch ihre Grenzen zu (er)kennen. Nach allem mit regulären Ausdrücken zu werfen, was mir vor die Flinte läuft, ist ebenso unsinnig wie sie pauschal zu verdammen.

            --
            Once is a mistake, twice is jazz.