hawkmaster: Regulärer Ausdruck, Hilfe gesucht

Hallo zusammen,
nachdem ich nun schon stundenlang herumprobiere brauche ich doch eure Hilfe.

Ich suche nach Muster in einer Textdatei: z.b.

*OpenUI *DeckOpt/Einheit:Pick
...
...
*CloseUI: *DeckOpt

Folgendes funktioniert:
if (preg_match_all("#\OpenUI \".$element."(/(.*?):|:) (.*?)\CloseUI: \".$element."#s", $string1, $contents)){

Jetzt gibt es aber auch Stellen in der Datei die nicht *OpenUI oder *CloseUI heissen sondern z.b. *OpenUIUWP und *CloseUIUWP
also etwa,
*OpenUIUWP *DeckOpt/Einheit:Pick
...
...
*CloseUIUWP: *DeckOpt

Ich dachte ich erweitere die Regex mit \*OpenUI.*?
also "ein beliebiges Zeichen, einmal oder keinmal".

if (preg_match_all("#\OpenUI.*? \".$element."(/(.*?):|:) (.*?)\CloseUI.*?: \".$element."#s", $string1, $contents)){

Leider funktioniert das aber nicht.
Kann mir jemand helfen?

vielen Dank und viele Grüße
hawk

  1. Hallo hawkmaster!

    Wenn du das Leerzeichen als Kriterium nimmst, das die beiden Teile trennt, ungefähr so:

    »OpenUI[^ ]+«

    Gruß Uwe

    1. Hallo Uwe,
      danke erstmal für deine Hilfe.

      Wenn du das Leerzeichen als Kriterium nimmst, das die beiden Teile trennt, ungefähr so:
      »OpenUI[^ ]+«

      hmm,
      eigentlich meinte ich kein Leerzeichen sondern das sowohl
      *OpenUI
      gefunden wird, als auch
      *OpenUIXYZ
      oder *OpenUIWQT

      Also es fängt immer mit *OpenUI an, aber es gibt halt auch Stellen wo hintendran noch ein paar Zeichen folgen.

      vielen Dank und viele Grüße
      hawk

      1. Hallo hawkmaster!

        Also es fängt immer mit *OpenUI an,

        Genau, also »*OpenUI«

        aber es gibt halt auch Stellen wo hintendran noch ein paar Zeichen folgen.

        Die Frage ist welche Zeichen oder auch welche Zeichen nicht oder auch bis zu welchem Zeichen.

        Nehmen wir (aus visuellen Gründen) statt eines Leerzeichens das Gradzeichen »°«.

        Deine Beispiele sähen dann so aus:

        »*OpenUI°*DeckOpt/Einheit:Pick«
        »*OpenUIUWP°*DeckOpt/Einheit:Pick«

        Die negative Zeichenklasse »[^°]« umfasst alle Zeichen außer dem Zeichen »°« und frisst damit jedes Zeichen, das kein Gradzeichen ist. Oder anders ausgedrückt, sie frisst alles bis sie auf ein Gradzeichen stößt. Man kann das Gradzeichen hier als Stoppzeichen auffassen.

        Bezugstext: »*OpenUI°*DeckOpt/Einheit:Pick«
        Muster: »*OpenUI[^°]*«
        Ergebnis: »*OpenUI«

        Bezugstext: »*OpenUIUWP°*DeckOpt/Einheit:Pick«
        Muster: »*OpenUI[^°]*«
        Ergebnis: »*OpenUIUWP«

        An das Muster »*OpenUI[^°]*« musst du natürlich noch den Rest deines Musters anhängen.

        Beachte, dass ich gegenüber dem ursprünglichen Vorschlag »OpenUI[^ ]+« den Quantifizierer »+« gegen den Quantifizierer »*« ausgetauscht habe.

        Gruß Uwe

        1. Hallo Uwe,
          vielen herzlichen Dank für deine Erklärung.
          Etwas klarer ist es mir geworden.
          So klappt es nun mit allem.

          if (preg_match_all("#\OpenUI[^ ]* \".$element."(/(.*?):|:) (.*?)\CloseUI[^ ]*: \".$element."#s", $string1, $contents)){

          So wird der Abschnitt:

          *OpenUIUWP *EFRange/Bereich:PickOne
          *OrderDep: 70.0
          *EFPageRange All/Alle: ".....
          ....
          ....
          *End
          *CloseUIUWP: *EFPageRange

          als auch:

          *OpenUI *EFRange/Bereich:PickOne
          *OrderDep: 70.0
          *EFPageRange All/Alle: ".....
          ....
          ....
          *End
          *CloseUI: *EFPageRange

          Ich dachte allerdings zuerst ich müsste es so schreiben:

          if (preg_match_all("#\OpenUI[^ ]*\".$element......
          also ohne zusätzlicher Leerstelle
          \OpenUI[^ ]*\
          anstatt richtig:
          \OpenUI[^ ]* \

          Deine Syntax mit [^ ]* bedeutet doch eigentlich "Kein oder mehrere Leerzeichen" oder?
          Dann müsste es doch eigentlich auch mit \OpenUI[^ ]*\  funktionieren?

          Und bei dem CloseUI war ich mir ganz unsicher denn zwischen CloseUI und dem Doppelpunkt : kommen doch eigentlich nie Leerzeichen vor sondern andere Zeichen.

          Hm, ich werde nochmals darüber grübeln bis ich es richtig kapier. Die Reguläre Ausdrücke sind manchmal wirklich nicht leicht zu verstehen.

          vielen Dank und viele Grüße
          hawk

          1. Hallo hawk!

            Beachte: Das Gradzeichen »°« steht symbolisch für das  Leerzeichen

            Syntax mit [^°]* bedeutet doch eigentlich "Kein oder mehrere Leerzeichen" oder?

            Nein! Falsch!

            Es bedeutet "Kein oder mehrere Zeichen" der zugrundliegenden Zeichenmenge.

            Etwas genauer ausgedrückt, könnte man sagen, der Quantifizierer »*« verlangt Null bis - da er gierig ist - möglichst viele Zeichen, der zugrunde liegenden Zeichenmenge.

            Die zugrunde liegende Zeichenmenge wird durch die Zeichenklasse definiert. Eine Zeichenklasse kann positiv oder negativ beschrieben werden, positiv bedeutet, man beschreibt welche Zeichen zulässig sind, negativ bedeutet, man beschreibt, welche Zeichen nicht zulässig sind, alle anderen Zeichen sind damit automatisch zulässig.

            Die negative Zeichenklasse »[^°]« definiert nun eine Zeichenmenge, die ALLE Zeichen AUßER dem Leerzeichen umfasst. Der gierige Quantifizierer »*« sorgt dafür, dass so lange gefressen wird, bis ein Zeichen auftaucht, das nicht Bestandteil der definierten Zeichenmenge ist. Und das ist in diesem Falle nur ein einziges Zeichen, das Leerzeichen. In dieser Konstellation wirkt es quasi wie ein Stoppzeichen.

            Ich dachte allerdings zuerst ich müsste es so schreiben:

            if (preg_match_all("#\OpenUI[^ ]*\".$element......
            also ohne zusätzlicher Leerstelle
            \OpenUI[^ ]*\
            anstatt richtig:
            \OpenUI[^ ]*°\

            Das Leerzeichen ist NICHT Bestandteil der zugrundeliegenden Zeichenmenge, das Leerzeichen selber wird daher nicht gefressen, da es ja kein "gültiges" Zeichen ist. Das Leerzeichen sorgt dafür, dass das Musterelement »[^°]*« aufhört zu fressen, wird aber - wie bereits gesagt, von diesem Musterelement selber nicht gefressen. Das nächste Musterelement, hier also »°«, das dann an der Reihe ist, muss daher dieses Leerzeichen fressen, sonst würde es nicht weiter gehen. Beide Musterelemente zusammen sehen also so aus: »[^°]*°«.

            Und bei dem CloseUI war ich mir ganz unsicher denn zwischen CloseUI und dem Doppelpunkt : kommen doch eigentlich nie Leerzeichen vor sondern andere Zeichen.

            Der Doppelpunkt »:« ist ein gültiges Zeichen der Zeichenklasse »[^°]« und wird (wie jedes andere Zeichen, außer dem Leerzeichen), sofern er vor einem Leerzeichen auftaucht, gefressen. In deinen nachfolgenden Musterelementen musst du ihn also nicht mehr berücksichtigen, denn er wurde von »[^°]*« bereits gefressen.

            Gruß Uwe