Ankündigung

Einklappen
Keine Ankündigung bisher.

Verschachtelte Reguläre Ausdrücke

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Verschachtelte Reguläre Ausdrücke

    Hallo,
    ich habe folgendes Problem:
    ich möchte aus einer Zeile, die in etwa so aufgebaut ist:

    Code:
    Name(12.03.2011 - 14.06.2012; 17.07.2012 - 18.02.2013)

    Folgende Dinge extrahieren:
    Name
    12.03.2011
    14.06.2012
    17.07.2012
    18.02.2013

    Zudem gibt es die Möglichkeit, dass vor dem ersten Datum eines Abschnitts ein EX: stehen kann, aber nicht muss, also bspw:

    Code:
    Name(EX: 12.03.2011 - 14.06.2012; 17.07.2012 - 18.02.2013)

    oder

    Code:
    Name(12.03.2011 - 14.06.2012; EX: 17.07.2012 - 18.02.2013)


    Wie viele Datumsabschnitte kommen ist immer unterschiedlich, es können genau so gut 10 Zeiträume sein.

    Mein bisheriger Ansatz ist folgender:

    Code:
    (\w*) \((?:(EX: )?(\d{2}.\d{2}.\d{4}) (?:- (\d{2}.\d{2}.\d{4}))?(?:;\s)?)++\)

    Allerdings ist das Ergebniss nicht wie erwartet
    12.03.2011
    14.06.2012
    17.07.2012
    18.02.2013

    sondern lediglich
    17.07.2012
    18.02.2013


    Hat jemand eine Idee wo mein Fehler liegen könnte? Vermutlich ist das ganz einfach aber ich bin noch neu was reguläre Ausdrücke angeht.

    Hier ein par "gültige" Zeilen, welche möglich sein müssen:
    Anna (14.12.2014 - 13.02.2015)
    Bernd (10.03.2011 - 16.04.2011; 14.04.2012 - 18.07.2012)
    Chris (24.12.2013)
    David (EX: 11.12.2013 - 19.04.2014)
    Emil (EX: 16.07.2011)
    Frank (EX: 09.12.2014 - 16.04.2015; 13.06.2011 - 18.05.2013)
    Gertrut (05.11.2013 - 09.12.2013; EX: 09.12.2013 - 14.05.2015; 14.05.2015 - 20.06.2014)
    Hanna (14.12.2011 - 16.01.2012; EX: 16.01.2012)
    Igor (10.10.2010 - 11.11.2011; 12.12.2012 - 13.01.2013; 14.02.2013 - 14.02.2014; 15.03.2015 -16.04.2016)

    Liebe Grüße


  • #2
    Ganz Spontan?

    Die eine Möglichkeit wäre den String bei den Leerstellen zum explodieren zu bringen, wobei vorher solltest du die ( ; ) - durch eine Leerstelle replacen, da ich grade sehe, die Zeichenkette ist nicht immer eindeutig:
    mal so
    14.05.2015 - 20.06.2014
    mal so
    15.03.2015 -16.04.2016
    Und dann mithilfe eines Regulären Ausdrucks, wobei dieses Datumsformate noch recht einfach zu regexen sind, die Datumswerte matchen.

    Gibt aber durchaus schönere Varianten. Man könnte auch den Regulären Ausdruck an den Datumsstellen splitten und dann weiter arbeiten...
    Die Jatravartiden auf Viltwodl VI können den Kram von dir auch nicht nachvollziehen

    Kommentar


    • #3
      Daran hab ich auch gedacht aber mir wurde auch gesagt dass das unsauber sei und spätestens bei Namen mit leerzeichen würde es da auch Probleme geben. Dass da ein Leerzeichen bei Igor fehlt ist nur ein tippfehler.


      Chris

      Kommentar


      • #4
        reg. Ausdrücke können m.W. keine Wiederholungen capturen. Dir bleibt also nur die Variante, das nativ zu programmieren*). Ich kann daran auch nichts unsauberes finden.

        *) oder die maximal möglichen Funde im Ausdruck explizit aufzuführen. Aber das ist erst mal unsauber.


        [Ergänzung]
        Folgende Dinge extrahieren:
        Name
        12.03.2011
        14.06.2012
        17.07.2012
        18.02.2013

        Zudem gibt es die Möglichkeit, dass vor dem ersten Datum eines Abschnitts ein EX:
        Damit gingen in Deinem Parsing Informationen verloren. Sowohl die Art des Datums (Anfang oder Ende), als auch das EX solltest Du auf jeden Fall mit auslesen, auch wenn Du es aktuell nicht verwendest.
        --

        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
        Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


        --

        Kommentar


        • #5
          Du kannst dich natürlich auch voll und ganz auf die Strucktur stürzen.

          In deiner Zeichenkette ist entweder ein EX oder kein EX vorm ersten Datum.
          Soviel kann man sich ja schonmal merken und falls vorhanden, rausschmeißen.

          Zuerst kommt ein Name,
          dann eine Klammer auf,
          dann kommt ein Datum in der Form xx.xx.xxxx,
          Falls jetzt eine Klammer zu kommt, juhuuu Ende,
          Wenn nicht könnte es sein, dass direkt ein Semikolon kommt.....usw

          Zudem haben diese Zeichenkette eigentlich nur zwei Bereiche. Ähnlich wie im Matheunterricht. Vor der Klammer und hinter der Klammer. Die Leerstellen sind für dich nur beim Namen wichtig. Alles was in der Klammer steht, bräuchte so wie es aussieht keine Leerzeichen.....

          Wie war das noch Bottom Up? Details lösen und sich damit zu Groben durcharbeiten.
          Die Jatravartiden auf Viltwodl VI können den Kram von dir auch nicht nachvollziehen

          Kommentar


          • #6
            Wie war das noch Bottom Up? Details lösen und sich damit zu Groben durcharbeiten.
            Mit Verlaub, Moewe, vielleicht liest Du -trotz 30 Grad- den Ausgangspost mal aufmerksam und siehst, dass er das alles schon getan hat. Die Frage löst Deine Beschreibung jedenfalls nicht.
            --

            „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
            Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


            --

            Kommentar


            • #7
              Sowas?

              PHP-Code:
              <?php
              $data 
              = <<<DATA
              Anna (14.12.2014 - 13.02.2015)
              Bernd (10.03.2011 - 16.04.2011; 14.04.2012 - 18.07.2012)
              Chris (24.12.2013)
              David (EX: 11.12.2013 - 19.04.2014)
              Emil (EX: 16.07.2011)
              Frank (EX: 09.12.2014 - 16.04.2015; 13.06.2011 - 18.05.2013)
              Gertrut (05.11.2013 - 09.12.2013; EX: 09.12.2013 - 14.05.2015; 14.05.2015 - 20.06.2014)
              Hanna (14.12.2011 - 16.01.2012; EX: 16.01.2012)
              Igor (10.10.2010 - 11.11.2011; 12.12.2012 - 13.01.2013; 14.02.2013 - 14.02.2014; 15.03.2015 - 16.04.2016)
              DATA;

              $data explode("\n"$data);
              $rows = [];

              foreach(
              $data as $line) {
                  
              $result = ['line' => $line];
                  
              preg_match('/^(?P<name>\w+)/'$line$matches);
                  
              $result['name'] = $matches['name'];
                  
              preg_match_all('/(?:(?P<datum1>\\d{2}\\.\\d{2}\\.\\d{4})(?:\\s*\\-\\s*(?P<datum2>\\d{2}\\.\\d{2}\\.\\d{4}))?)/'$line$matches);
                  
              $result['datum-start'] = $matches['datum1'];
                  
              $result['datum-ende'] = $matches['datum2'];
                  
              $rows[] = $result;
              }

              print_r($rows);
              Standards - Best Practices - AwesomePHP - Guideline für WebApps

              Kommentar


              • #8
                Bei Regulären Ausdrücken wird nur immer an preg_match + preg_replace gedacht.
                preg_split ist genau so mächtig. Nur mal so als Ansatz:
                PHP-Code:
                $text 'Gertrut (05.11.2013 - 09.12.2013; EX: 09.12.2013 - 14.05.2015; 14.05.2015 - 20.06.2014)';

                $array array_filter(preg_split('~[(;\- )]+(EX:)? ?~',$text)); 
                Code:
                array (
                  0 => "Gertrut",
                  1 => "05.11.2013",
                  2 => "09.12.2013",
                  3 => "09.12.2013",
                  4 => "14.05.2015",
                  5 => "14.05.2015",
                  6 => "20.06.2014",
                )
                Klappt leider nicht immer mit so einen einfachen RegEx wie hier.

                LG jspit
                PHP-Klassen auf github

                Kommentar


                • #9
                  Der Ansatz ist gut! Aber die alleinstehenden Datumsangaben kann man damit schlecht unterscheiden.
                  Standards - Best Practices - AwesomePHP - Guideline für WebApps

                  Kommentar


                  • #10
                    Ich würde auch ein mehrdimensionales Array als Resultat bevorzugen. Eine andere Variante
                    PHP-Code:
                    $array array_filter(preg_split('~ \(|; EX: |; |\)~',$text)); 
                    liefert das:
                    Code:
                    array (
                      0 => "Gertrut",
                      1 => "05.11.2013 - 09.12.2013",
                      2 => "09.12.2013 - 14.05.2015",
                      3 => "14.05.2015 - 20.06.2014",
                    )
                    Dies kann dann nach Bedarf weiterverarbeitet werden.
                    PHP-Klassen auf github

                    Kommentar


                    • #11
                      Ich verstehe nicht wofür EX genau steht, und frage mich ob es wirklich was bringt, wenn man nur die Daten ausliest und sammelt. Vorallem wenn z.b.

                      DatumVon - DatumBis; DatumStehtAlleineHier ... wie wird Unterschieden welche "Blocks" zusammengehören?

                      Ich weiss ja nicht, aber wenn man das in Zukunft noch braucht für eine ernsthafte App wäre es ggf. hilfreich diese Zusatzinfos auch noch zu speichern.

                      Ansonsten finde ich die Lösung von rkr am Besten. Ich persönlich würde das Format manuell parsen und jeweils ein Objekt zurückgeben, dass man dann auch super testen kann (Unit Tests) und sicherstellen, dass der Parser funktioniert

                      Weiss aber nicht ob das zu advanced ist bzw. overkill für dein Problem. Ich find Regex extrem praktisch, aber wenn irgendwas abweicht oder geändert werden muss ist es oftmal eher doof. Vorallem ist man mit einem manuellen Parser auch flexibler. (Und so schwierig ist das Format auch wieder nicht).

                      Was meint ihr? Am Ziel vorbeigeschossen oder durchaus Überlegenswert?
                      Neu bei PHP, lerne aktuell OOP

                      Kommentar


                      • #12
                        preg_split('~ \(|; EX: |; |\)~'
                        Da Du nicjt weißt,was im Namen steht.. eher nicht.
                        --

                        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                        Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                        --

                        Kommentar


                        • #13
                          Ja, ich bin von realen Namen ausgegangen. Nicknamen mit runden Klammern oder die ein 'EX:' enthalten funktionieren nicht.
                          PHP-Klassen auf github

                          Kommentar

                          Lädt...
                          X