Ralf: preg_match_all: Bestimmte Wortbausteine aus String lesen.

Hallo,

ich möchte bestimmte Wortbausteine aus einen String auslesen.
Ein Wortbaustein besteht immer aus 2 feste Anfangszeichen (##wort1, ##wort2, etc...).

Leider funktioniert mein regulärer Ausdruck nicht. Es werden zwar alle Wörter gefunden,
jedoch wird nach ## abgeschnitten.

Beispiel

$data = "Ich bin ein Text mit 3 Wortbausteinen: ##wort1 und ##wort2 und ##wort3.

preg_match_all("@##.*?@si", $data, $matches);

Ausgabe $matches:

array(1) { [0]=>  array(3) { [0]=>  string(2) "##" [1]=>  string(2) "##" [2]=>  string(2) "##" } }

Kann mir jemand mit den Ausdruck helfen?

Danke,
Ralf

  1. preg_match_all("@##.*?@si", $data, $matches);

    Du sagst mit .*?
    "lies auf eine nicht gierige Art und Weise möglichst Null oder mehr Zeichen".

    Null gelesene Zeichen sind damit ausreichend für einen match.
    Du willst aber offenbar _gierig_ möglichst viele Zeichen Lesen, die der Zeichenklasse TextbausteinZeichen angehören.

    Definiere also die Zeichenklasse für TextbausteinZeichen

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Definiere also die Zeichenklasse für TextbausteinZeichen

      mfg Beat

      In etwa so: @##[a-zA-Z0-9]+@si ???

      Aber was ist mit den ganzen Sonderzeichen und Zeichensätzen?

      ##teléfono
      ##123öäü_+

      Die würden dann doch gar nicht gelesen werden, oder?

      Danke für Hilfe,
      Ralf

      1. In etwa so: @##[a-zA-Z0-9]+@si ???
        Aber was ist mit den ganzen Sonderzeichen und Zeichensätzen?

        ##teléfono
        ##123öäü_+

        Die würden dann doch gar nicht gelesen werden, oder?

        Du brauchst aber eine Definition für gültige Zeichen.

        Was machst du mit
        ##telé##fono
        oder
        ##telé fono

        Werde dir klar, welche Zeichen nicht als Bezeichner des Textbausteins vorkommen dürfen.
        Das heisst, definiere den Datentyp "Textbaustein" bevor du ihn verwendest.

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische
        1. ##telé##fono (sind 2 Wortbausteine)
          ##telé fono (ist 1 Wortbaustein)

          Damit würrde es doch gehen, oder?

          @##[[:alnum:][:cntrl:][:punct:]]+@si

          Gruß,
          Ralf

          1. ##telé##fono (sind 2 Wortbausteine)
            ##telé fono (ist 1 Wortbaustein)

            Damit würrde es doch gehen, oder?

            @##[[:alnum:][:cntrl:][:punct:]]+@si

            Wie sind [:alnum:][:cntrl:][:punct:] definiert?
            Sind diese vom Locale unabhängig?

            Was soll geschehen bei
            Ich sende ihnen, ##gender ##lastname, eine Antwort...
            Gehört das Komma zum Textbaustein-Identifikator
            Was versprichst du dir von [:cntrl:] als Teil eines Identifikators?
            Insbesondere von \u0000 ?
            Warum willst du mit [:alnum:] die Zeichen A-Za-z0-9 zulassen, aber nicht éêè?

            mfg Beat

            --
            ><o(((°>           ><o(((°>
               <°)))o><                     ><o(((°>o
            Der Valigator leibt diese Fische
            1. ##telé##fono (sind 2 Wortbausteine)
              ##telé fono (ist 1 Wortbaustein)

              Damit würrde es doch gehen, oder?

              @##[[:alnum:][:cntrl:][:punct:]]+@si

              Wie sind [:alnum:][:cntrl:][:punct:] definiert?
              Sind diese vom Locale unabhängig?

              Was soll geschehen bei
              Ich sende ihnen, ##gender ##lastname, eine Antwort...
              Gehört das Komma zum Textbaustein-Identifikator

              Nein

              Was versprichst du dir von [:cntrl:] als Teil eines Identifikators?
              Insbesondere von \u0000 ?
              Warum willst du mit [:alnum:] die Zeichen A-Za-z0-9 zulassen, aber nicht éêè?

              mfg Beat

              Deswegen bin ich ja auf die Hilfe angewiesen. ;-)

              Mit meinen Erfahrungen bin ich an die Grenzen gestoßen.

              Wie würdest Du einen Ausdruck angeben, der auch eventuelle Probleme berücksichtigt?

              Danke für Hilfe,
              Ralf

              1. Hi,

                Wie würdest Du einen Ausdruck angeben, der auch eventuelle Probleme berücksichtigt?

                Wenn man einen solchen erstellen will, muss man erst mal "eventuelle Probleme" genau erkennen und definieren.

                Bzw. andersherum, den Aufgabenumfang, den der Ausdruck abdecken soll, muss man vor seiner Erstellung erst mal exakt festlegen.

                MfG ChrisB

                --
                Light travels faster than sound - that's why most people appear bright until you hear them speak.
              2. Wie würdest Du einen Ausdruck angeben, der auch eventuelle Probleme berücksichtigt?

                Zuerst würde ich eine Syntax definieren für den Datentyp
                TextbausteinIdentifikator

                Ein textbaustein

                • muss beginnen mit ##
                • gefolgt von 1 oder mehr Zeichen aus [A-Za-z0-9_]

                sorry; in Perl:

                my $TextbausteinIdentifikator = qr/##[A-Za-z0-9_]+/;

                Diese Syntax gilt es in der Aplikation an die Anwender halt mitzuteilen.
                Mag sie auch beschränkt sein, so erspart sie dir viele Probleme.

                Jetzt kann ich zuverlässig parsen
                $text =~ s/($TextbausteinIdentifikator)/replacetoken($1)/e;

                Das ist eine RE mit callback Funktion.

                Die schlichte Wahrheit ist, dass Reguläre Expressions und Unicode-Zeichen über den ASCII Bereich hinaus schlecht miteinander Tango tanzen.

                mfg Beat

                --
                ><o(((°>           ><o(((°>
                   <°)))o><                     ><o(((°>o
                Der Valigator leibt diese Fische
              3. Wie würdest Du einen Ausdruck angeben, der auch eventuelle Probleme berücksichtigt?

                Eventuell ist es einfacher zu definieren welche Zeichen nicht mehr zu einem Wort gehören.

                1. Wie würdest Du einen Ausdruck angeben, der auch eventuelle Probleme berücksichtigt?
                  Eventuell ist es einfacher zu definieren welche Zeichen nicht mehr zu einem Wort gehören.

                  Hi Sam.
                  Ha Joe, was darfs denn heute sein?
                  Ich will kein Bier?
                  Verstehe, noch was?
                  Ich will ach kein Soda.
                  Ok kein Soda und kein Bier, haben wir...
                  ...

                  mfg Beat

                  --
                  ><o(((°>           ><o(((°>
                     <°)))o><                     ><o(((°>o
                  Der Valigator leibt diese Fische
                  1. Dobar dan.
                    Dobar dan. Sprechen Sie Deutsch?
                    Viel wenig.
                    Ahh - ich möchte etwas zum Mittag essen aber ich kann die Karte nicht lesen. Können Sie mir was empfehlen? Aber kein Fisch bitte.
                    Hunchen vielleicht?
                    Ja bitte.

                    Du weißt doch genausowenig, welche Zeichen zum Wort gehören, wie ich, welche nicht zum Wort gehören. Wir wissen beide nicht, ob Ralf eher das eine oder eher das andere definieren kann.

                    Kann es eventuell besser/einfacher sein zu definieren welche Zeichen nicht mehr zu einem Wort gehören? Ja, definitiv, möglicherweise sind es nur Leerzeichen, Komma, Rautenzeichen und das Stringende.

                    1. Du weißt doch genausowenig, welche Zeichen zum Wort gehören, wie ich, welche nicht zum Wort gehören. Wir wissen beide nicht, ob Ralf eher das eine oder eher das andere definieren kann.

                      Kann es eventuell besser/einfacher sein zu definieren welche Zeichen nicht mehr zu einem Wort gehören? Ja, definitiv, möglicherweise sind es nur Leerzeichen, Komma, Rautenzeichen und das Stringende.

                      Nein, es kann einfacher sein, einen neuen Sprachkontext durch eine definierte Start-Zeichenfolge und eine definierte End-Zeichenfolge zu ähm definieren.
                      {{irgend%ein{{}}chinesischerIdentifier}}

                      mfg Beat

                      --
                      ><o(((°>           ><o(((°>
                         <°)))o><                     ><o(((°>o
                      Der Valigator leibt diese Fische
                      1. Kann es eventuell besser/einfacher sein zu definieren welche Zeichen nicht mehr zu einem Wort gehören? Ja, definitiv, möglicherweise sind es nur Leerzeichen, Komma, Rautenzeichen und das Stringende.

                        Nein, es kann einfacher sein, einen neuen Sprachkontext durch eine definierte Start-Zeichenfolge und eine definierte End-Zeichenfolge zu ähm definieren.

                        Und wie kommt man dazu?

                        1. Kann es eventuell besser/einfacher sein zu definieren welche Zeichen nicht mehr zu einem Wort gehören? Ja, definitiv, möglicherweise sind es nur Leerzeichen, Komma, Rautenzeichen und das Stringende.

                          Nein, es kann einfacher sein, einen neuen Sprachkontext durch eine definierte Start-Zeichenfolge und eine definierte End-Zeichenfolge zu ähm definieren.

                          Und wie kommt man dazu?

                          Dann gebe ich die Antwort. Indem man die End-Zeichenfolge mit Hilfe der einen, der anderen oder einer weiteren Methode nach dem Wortende einfügt. Wem schwindlig ist, das liegt am im Kreis drehen.

                2. Hi,

                  Eventuell ist es einfacher zu definieren welche Zeichen nicht mehr zu einem Wort gehören.

                  Denke ich auch.

                  »»»» Ein Wortbaustein besteht immer aus 2 feste Anfangszeichen (##wort1, ##wort2, etc...).

                  Man benötigt also einen regulären Ausdruck, der Wörter sammelt, die:

                  • mit 2 ## beginnen
                      '~#{2}

                  • gefolgt von beliebig vielen nicht white-spaces, nicht-Beistrichen, nicht-rauten.
                      '~#{2}[^\s#,]+

                  • wobei ja nur wörter erwünscht sind, also klammern wir
                      $pattern = '~#{2}([^\s#,]+)~is';

                  Nun sollten wir ein array bekommen, das an [0] alle ##wörter und [1] alle wörter enthält:

                  preg_match_all($pattern,$str,$out);
                  print_r($out[1]);

                  Viel Erfolg,
                  Jonny 5

                  1. Eventuell ist es einfacher zu definieren welche Zeichen nicht mehr zu einem Wort gehören.
                    Denke ich auch.

                    Viel Erfolg,

                    Wie schon besprochen, darfst du jetzt noch alle verbotenen Satzzeichen mit aufnehmen, egal ob sie im ASCI Bereich oder im erweiterten Unicode Bereich auftreten.
                    Viel vergnügen auf dir, wenn du sagst: Ich will kein Bier.

                    mfg Beat

                    --
                    ><o(((°>           ><o(((°>
                       <°)))o><                     ><o(((°>o
                    Der Valigator leibt diese Fische
                    1. Wie schon besprochen, darfst du jetzt noch alle verbotenen Satzzeichen mit aufnehmen, egal ob sie im ASCI Bereich oder im erweiterten Unicode Bereich auftreten.

                      Also möglicherweise keine.

                      Viel vergnügen auf dir, wenn du sagst: Ich will kein Bier.

                      Schweren Tag gehabt? Ein Tabulator gefällig?
                      Ich trinke kein whitespace, ich will was whitespacefreies, alles andere außer einem img ist mir recht.

                    2. Hi,

                      Wie schon besprochen, darfst du jetzt noch alle verbotenen Satzzeichen mit aufnehmen, egal ob sie im ASCI Bereich oder im erweiterten Unicode Bereich auftreten.

                      Also, das läßt sich doch anpassen, wie man möchte.

                      Also nur uni code points, und es handelt sich auch um unicode?

                      Dann etwas in der Art erweitern:

                      '~#{2}(\p{L}+)~uis'

                      oder zahlen und white-spaces auch noch?

                      '~#{2}([\p{L}\p{N}\s]+)~uis'

                      usw. Wo ist das Problem? Vielleicht mit der Materie beschäftigen :)

                      schöne Grüße nochmal,
                      Jonny 5