s.oliver: Regex immer mal wieder

Beitrag lesen

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