Ankündigung

Einklappen
Keine Ankündigung bisher.

RegEx zur Suche von fester Zeichenkette mit Darauffolgendem

Einklappen

Neue Werbung 2019

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

  • RegEx zur Suche von fester Zeichenkette mit Darauffolgendem

    Grüß Euch,

    ich versuche folgendes zu erreichen:

    ich habe einen Array der Form
    array(0 => "blablub: 2323", 1 => "Rektaszension: 03h50m18.9596s", 2 => test sonstwas);

    ich versuche nun, den Schlüssel des Arrays herauszufinden, in dem die Rektaszension steht, denn ich brauche die Nummer. Diese ist in jedem array anders und es muss mitgeprüft werden, ob "h" "m" und "s" auch in der Zeichenkette stehen.

    Mein Regex ist bisher so, funktioniert aber leider nicht und prüft nicht auf die Buchstaben. Bin leider kein Regex-Experte.
    foreach....:
    "/\sRektaszension.*?)\\r\\n/"
    endforeach;

    Danke schonmal!

  • #2
    /Rektaszension:\s*(\d+)h(\d+)m(\d+)s$/

    Kommentar


    • #3
      Woran scheiterts?

      Mit array_values() kannst du die Werte des Arrays ermitteln, mit explode(":", ..) diese aufsplitten ..

      Kommentar


      • #4
        Hallo Slava!

        Man, Dich trifft man ja auch in jedem Forum.
        Vielen Dank. Dein Regex hat teilweise funktioniert - nur teilweise, weil ich die Umstände ein bisschen widrig beschrieben habe.

        Folgendes benutze ich nun mit Erfolg:
        ~(?<=Rektaszension: ).*~

        *EDIT:

        Hallo Zergling,
        ich bin nicht unbedingt ein Freund von regulären Ausdrücken; Allerdings sollte hier die Berechnungsgeschwindigkeit zw. String/ Arrayfunktionen und dem schlanken regex nicht so unterschiedlich sein.

        Eigentlich ist Deine Möglichkeit bei Operationen schneller, was hier nicht so zählt. Mit den beiden regex-Zeilen habe ich den Code nun ein bisschen schlanker gehalten.

        Vielen Dank auch an Dich!

        Grüße

        Kommentar


        • #5
          PHP-Code:
          <?
          $array = array(0 => "blablub: 2323", 1 => "Rektaszension: 03h50m18.9596s", 2 => 'test sonstwas');

          $found = preg_grep ($pattern = '#^Rektaszension:\s*?(.*)#' , $array); // Suche
          // Schlüssel des ersten Matches
          echo key ($found); 
          // Wert des ersten Matches, also 03h50m18.9596s
          echo preg_replace ($pattern , '$1' , reset ($found));

          Kommentar


          • #6
            und es muss mitgeprüft werden, ob "h" "m" und "s" auch in der Zeichenkette stehen
            Hmmm wie wollt ihr das prüfen, wenn (.*?) da steht ?
            Dann könnte da alles mögliche stehen
            Oder hab ich was falsch verstanden ?

            Kommentar


            • #7
              Und offensichtlich hats sich der TE anders überlegt
              Vielen Dank. Dein Regex hat teilweise funktioniert - nur teilweise, weil ich die Umstände ein bisschen widrig beschrieben habe.

              Folgendes benutze ich nun mit Erfolg:
              ~(?<=Rektaszension: ).*~

              Kommentar


              • #8
                Hallo CIX, hallo Nikosch,

                ich war wohl anfangs ein bisschen über's Ziel hinausgeschosen. Meine Anwendung des Regex prüft nun nicht nach h, m und s. Das sollte ich sicherlich noch ändern. Hat jemand evtl einen guten Einfall, ohne dass der Regex zu einem "Monster" heranwächst?

                .* ist nicht allzu geeignet dafür.

                Danke Euch für die engagierte Hilfe.

                Kommentar


                • #9
                  Slavas Ausdruck traf es schon fast. Problem war wahrscheinlich nur das nicht unterstützte Komma für Sekunden - /Rektaszension:\s*(\d+)h(\d+)m(\d+)s$/ untersttützt nur ganzzahlige Sekunden.

                  Versuch mal:
                  PHP-Code:
                  <?
                  // erlaubt . und , für Nachkommastellen
                  $found = preg_grep ($pattern = '#^Rektaszension:\s*?(\d+)h(\d+)m((\d+)(?:[\.,](\d+)))s#' , $array);
                  /*
                  Über $1-$5 sind jetzt die Winkel ablesbar:
                  $1 h
                  $2 m
                  $3 s - komplett
                  $4 s - Ganzzahlanteil
                  $5 s - Nachkommastellen
                  */
                  echo preg_replace ($pattern , '$1 h $2 m $3 s' , reset ($found));
                  Mit einem i hinter dem Zweiten # könntest Du bspw.auch die Unabhängigkeit von Groß/Kleinschreibung erlauben.
                  Leider führst Du nicht genau aus, was passieren soll, wenn das h-m-s Muster nicht vollständig ist.

                  Kommentar


                  • #10
                    Zitat von nikosch77
                    Slavas Ausdruck traf es schon fast. Problem war wahrscheinlich nur das nicht unterstützte Komma für Sekunden - /Rektaszension:\s*(\d+)h(\d+)m(\d+)s$/ untersttützt nur ganzzahlige Sekunden.
                    stimmt ,
                    ich habe es nicht berücksichtigt, dass in sekunden ein float steht.

                    Kommentar


                    • #11
                      Hi Nikosch, Hallo Slava,

                      Ich erkläre jetzt einfach nochmal ein bisschen genauer, was ich brauche. WObei ich sagen muss, dass Dein Ausdruck es schon recht gut auf den Punkt bringt.

                      ich lese aus der Datenbank ein Feld aus, dass einen recht langen Text enthält, wobei Zeilenumbrüche wie gehabt durch \r\n gekennzeichnet sind.

                      In diesem Text muss ich das erste Vorkommen von "Rektaszension: 03h50m18.9596s" (wobei die Zahlen für das jeweilige Feld eben variieren), bzw. "Deklination: +38 51' 33.381" auslesen, die eben genau in der Form nur mit variablen Zahlen auftreten. Der Text ist recht durcheinander und ungegliedert - bis auf die Zeilenumbrüche.

                      Die Worte "Rekt." und "Dekl." kommen im Text häufiger vor, aber - wie gesagt - brauche ich nur das erste vorkommen der oben genannten Form.

                      Mein Regex hat bis jetzt nur funktioniert, weil die genannte Form meistens das erste Vorkommen ist, aber eben nicht immer. Bisher explode ich in PHP das gesamte Feld und lese mit Foreach den entstandenen Array aus, wobei ich mit dem bisherigen Regex (preg_match('/(?<=Rektaszension: ).*/', $valuedetails, $ra) auf das Vorkommen des Gesuchten Begriffs teste.

                      Ist Dein oben genannter Regex dafür ausgelegt, oder muss ich noch auf etwas achten?

                      Vielen Dank!

                      Gruß,
                      pepe

                      Kommentar


                      • #12
                        Es gibt ein paar Punkte, die zu beachten sind:

                        - können oder müssen Nachkommastellen vorkommen (mein Ausdruck liest beides aus)
                        - wo stehen Leerzeichen im Suchdatensatz. Ist es denkbar, dass Abweichungen bestehen
                        - Ist es denkbar, dass ein Suchdatensatz durch einen Zeilenumbruch betroffen ist
                        - Sind h m s immer in Kleinschreibung
                        - Soll Deklination: +38 51' 33.381'' analog behandelt werden oder extra (weil z.B. noch Umrechnungen nötig sind)?
                        Denkbar wäre im ersten Fall dieser Ausdruck (ungetestet):
                        PHP-Code:
                        <?
                        $found = preg_grep ($pattern = '#^(?:Rektaszension:\s*?|Deklination:\s*?)(?:(\d+)h|(\+\d+))(\d+)[m\']((\d+)(?:[\.,](\d+)))(?:s|\'\'|")#' , $array);
                        /*
                        Über $1-$6 sind jetzt die Winkel ablesbar:
                        $1 h bei ... h Angabe
                        $2 h bei + ... Angabe
                        $3 m
                        $4 s - komplett
                        $5 s - Ganzzahlanteil
                        $6 s - Nachkommastellen
                        */
                        - Wozu wird "explodiert"? preg_match () liefert auch aus ganzen Texten den Suchstring. Hier ist das s Flag zu setzen und ^zu entfernen.

                        Kommentar


                        • #13
                          Hi Nikosch,

                          erstmal danke für Dein Engagement.

                          - Explode benutze ich, dass der REGEX immer nur einen kurzen String zu prüfen hat, weil die Renderzeit durch einen langen Audruck hier wohl einen größeren Sprung nach oben machen würde. Textzeichen des Feldes ~5000. Das war allerdings ein subjektiver Eindruck über einige Jahre - hier muss ich also gestehen, dass ich bei der Erfahrungssammlung die Regex-Ausdrücke immer irgendwie umgangen habe.

                          Nun zum Thema:
                          -Nachkommastellen in Form eines Punktes - also Float-Zahl kommt nur in den Sekunden der Rekt. und Dekl. vor.
                          -Leerstellen gibt es nur bei der Deklination - und dort immer. Bei der Rekt. sind generell KEINE Leerstellen zwischen den Angaben. Hier ist die Datenintegrität auch beachtlich, will heißen, dass es hier auch keine Ausnahme gibt.
                          -h,m,s sind immer klein geschrieben
                          -Umrechnungen sind nicht nötig - diese werden später mit der Hand unter angabe der Parallaxen gemacht, weil diese u.U variieren können

                          Hier müsste ich auch nicht die einzelnen Zahlen bekommen, sondern es würde reichen, den kompletten ausdruck als String zu erhalten in Form von "03h50m18.9596s", bzw. '+38 51' 33.381"'.

                          -Ebenso kann man fest davon ausgehen, dass nach den Werten jeweils ein Zeilenumbruch statt findet.

                          Zu meinem Engagement: Ich bilde mich bereits weiter in der Regex-Thematik. Allerdings ist die Verantwortung, die mich mit dieser Applikation ereilt hat so hoch, dass ich bei den Regexes wirklich keinen Fehler machen will. Hier also nochmals ein "Danke".

                          Gruß,
                          Peter

                          Kommentar


                          • #14
                            Ohne Garantie auf Korrektheit, mal reduziert nach Deinen Angaben:

                            PHP-Code:
                            <?
                            $found = preg_grep ($pattern = '#(?:Rektaszension:\s*?|Deklination:\s*?)((?:\d+h|\+\d+\s*)\d+[m\']\s*\d+(?:[\.,]\d+)(?:s|\'\'|"))#' , $array);

                            print_r($found);
                            echo preg_replace ($pattern , '$1' , reset ($found));
                            /*
                            $1 sollte jetzt die komplette Angabe enthalten
                            */
                            ?>
                            Mit der explode-Geschichte bin ich nicht sicher. Zumal die obige Lösung 2 preg-Aktionen erfordert, weil preg_grep () keine Backreferences verarbeitet. Möglicherweise wäre ein einfaches preg_match () oder preg_replace () auf den Ausgangstext doch schneller. Schreib Dir einfach nen kleinen Timer mit microtime () - Bsp. im Manual - und spiel mal ein paar Fälle durch.

                            Ansonsten viel Spaß beim Lernen, es lohnt sich.

                            Kommentar


                            • #15
                              Wenns nicht performant ist einfach mit strpos() das erste Vorkommen dieser Schlüsselbegriffe suchen, dann mit substr() einen angemessenen nachfolgenden Teil rausschneiden und das preg_match() darüber laufen lassen. Nur für den Fall der Fälle ..

                              Zum RegExp kann ich nichts sagen, ?: sagt mir nichts (Assertions?) - Viel Glück also damit

                              Kommentar

                              Lädt...
                              X