Bernd: Regex-Frage

Hi,

Ich möchte in einem String alle Ausdrücke herausfiltern, die sich in eckigen Klammern befinden.

$string="[10xxx-yyy10] [20xxx-yyy5] [30xxx-yyy]";
$muster = '/[([a-zA-Z0-9-]+)'];
preg_match_all($muster, $string, $ergebnis);

ergibt aber

Array ( [0] => Array ( ) [1] => Array ( ) )

Was stimmt an m einer Regex nicht?

Bernd

  1. $muster = '/[([a-zA-Z0-9-]+)'];

    (Hmm, Tippfehler?)
    Das Muster wird mit / eingeleitet, muss quasi auch mit / (+ evt. Modifier) enden.
    Des weiteren Endet der String nicht.

    Mal davon ausgehend, dass dir beim tippen/C&P ein Fehler unterlaufen ist,

    [a-zA-Z0-9-]+

    Das wäre Laut deiner Beschreibung falsch, da du ja _alles_ haben willst.

    $muster = "/\[([^\\]]+)\]/";
    Wahrscheinlich musst du noch auf nicht-gierig setzen. (ungetestet)

    MfG
    bubble

    1. $muster = '/[([a-zA-Z0-9-]+)'];
      (Hmm, Tippfehler?)

      Jups, Tipfehler:

      $suchmuster = '/[([a-zA-Z0-9-]+)]/';

      So wird ein Schuh draus.

      Bernd

      P.S: Na, alles wollte ich nicht haben. [a-zA-Z0-9-]+) triffts genau. Sorry, ich hatte undeutlich gefragt.

      1. $suchmuster = '/[([a-zA-Z0-9-]+)]/';

        /[([a-z0-9-]+)]/i
        Damit wäre es sogar noch kürzer geschrieben ;)

        Wenn mich nicht alles täuscht, sogar:
        /[([\w\d-]+)]/

        MfG
        bubble

        1. $suchmuster = '/[([a-zA-Z0-9-]+)]/';

          /[([a-z0-9-]+)]/i
          Damit wäre es sogar noch kürzer geschrieben ;)

          Wenn mich nicht alles täuscht, sogar:
          /[([\w\d-]+)]/

          MfG
          bubble

          Regex-Spezialist, wie? ;-)

          Aber ok, dann habe ich auc h eine Nachfrage:

          Wie gehe ich am sinnvollsten vor, wenn ich aus meinem String jeden dieser Ausdrücke ala [10xxx-yyy10] in "Am 1.Februar hat Peter 10 jähriges Jubiläum alt umsetzen will"? Das "xxx" in allen Fällen ein gegebenes (mysql)Datum und das "yyy" steht jeweils für einen gegebenen Namen.

          Die Angaben wären somit:

          $datum = "2013-01-21";
          $Name = "Bernd";
          $string="[10xxx-yyy10]\n[20xxx-yyy5]\n[30xxx-yyy]";

          Gewünschtest Ergebnis:

          $string_neu="Am 01.02.2013 hat Bernd 10 jähriges Jubiläum\nAm 11.02.2013 hat Bernd 5 jähriges Jubiläum\nAm 21.02.2013 hat Bernd Jubiläum";

          Gruß, Bernd

          1. Wie gehe ich am sinnvollsten vor, wenn ich aus meinem String jeden dieser Ausdrücke ala [10xxx-yyy10] in "Am 1.Februar hat Peter 10 jähriges Jubiläum alt umsetzen will"? Das "xxx" in allen Fällen ein gegebenes (mysql)Datum und das "yyy" steht jeweils für einen gegebenen Namen.

            Die Angaben wären somit:

            $datum = "2013-01-21";
            $Name = "Bernd";
            $string="[10xxx-yyy10]\n[20xxx-yyy5]\n[30xxx-yyy]";

            Mir fällt grad auf das \w falsch ist >.< \w ist a-zA-Z0-9
            stattdessen verwende ich a-z in Verbindung mit dem Modifier i (caseInsensitive)

            Da würde ich ein ganz anderes Muster nehmen.

            wie man sieht besteht das Datum aus 4 Ziffern + "-" + 2 Ziffern +"-" + 2 Ziffern, ergibt das Teilmuster (\d{4})-(\d{2})-(\d{2})
            davon ausgehend das der Name nur aus Buchstaben besteht ist sein Teilmuster ([a-z]+)
            die vorderen Ziffern versteh ich nich also ignorier ich sie mit \d*
            die hinteren ziffern sind das jubiläum (\d*)

            das muster ergibt als /[\d.*(\d{4})-(\d{2})-(\d{2})-([a-z]+)(\d*)]/i

            Im folgendem ohne Erklärung (sollte so reichen):

              
            	$output = "";  
            	$str = "[102015-11-07-paul25]\n[102015-11-07-herbert]";  
            	$template = "Am %s.%s.%s hat %s %sjähriges Jubiläum\n";  
            	if(preg_match_all("/\[\d.*(\d{4})-(\d{2})-(\d{2})-([a-z]+)(\d*)\]/i",$str,$data))  
            		foreach($data[0] as $idx => &$unused)  
            			$output .= sprintf($template, $data[3][$idx],$data[2][$idx],$data[1][$idx],$data[4][$idx],($data[5][$idx]?$data[5][$idx]:"ein"));
            

            MfG
            bubble

            1. $output = "";
              $str = "[102015-11-07-paul25]\n[102015-11-07-herbert]";
              $template = "Am %s.%s.%s hat %s %sjähriges Jubiläum\n";
              if(preg_match_all("/[\d.(\d{4})-(\d{2})-(\d{2})-([a-z]+)(\d)]/i",$str,$data))
              foreach($data[0] as $idx => &$unused)
              $output .= sprintf($template, $data[3][$idx],$data[2][$idx],$data[1][$idx],$data[4][$idx],($data[5][$idx]?$data[5][$idx]:"ein"));

              
              >   
              > MfG  
              > bubble  
                
              Hi bubble,  
                
              wow! Mal abgesehen davon, dass Dein Code sehr gut arbeitet (und das, obwohl ich den gar nicht verstehe), ist das Problem ein klein wenig anders (vermutlich sogar leichter).  
                
              
              > $datum = "2013-01-21";  
              > $Name = "Bernd";  
              > $string="[10xxx-yyy10]\n[20xxx-yyy5]\n[30xxx-yyy]";  
                
              
              > Gewünschtest Ergebnis:  
                
              
              > $string\_neu="Am 01.02.2013 hat Bernd 10 jähriges Jubiläum\nAm 11.02.2013 hat Bernd 5 jähriges Jubiläum\nAm 21.02.2013 hat Bernd Jubiläum";  
                
                
              Das heißt,  
                
              - \n bleiben bestehen  
              - Die Zahl vor xxx ist die zum Datum $datum zu addierende Anzahl an Tagen  
              - xxx selber ist ein immer gleicher Begriff mit dem Namen "xxx"  
              - yyy ist immer der Name "Bernd"  
              - die Zahl hinter dem yyy ist die Anzahl des Jubiläums  
                
              Ist das so besser ausgedrückt?  
                
              Viele Grüße, Bernd
              
              1. [...] ist das Problem ein klein wenig anders (vermutlich sogar leichter).

                Ich glaub nicht das man das wirklich vergleichen kann, da es einfach 2 verschiedene Dinge sind ;p

                Ist das so besser ausgedrückt?

                Auf jeden Fall, verstehe ich jetzt was du vorhast. Allerdings finde ich die herangehensweise irgendwie ein wenig sonderbar.

                Jubiläen (ist das der Plural?) von derselben Sache sind doch immer in einem bestimmten Interval, ab Datum X. (Sprich Ladeneröffnung am Tage X, 1. Jubiläum = X+1 Jahr, 2. Jubiläum = X+2 Jahre) Quasi bräuchte man nur das Startdatum (Tag X), den Interval (1 Jahr) und die Nummer des Jubiläums.
                Datum und Name kommen ja aus einer Datenbank oder?
                Mit Daten arbeitet es sich leichter wenn sie bis zur Ausgabe eigentlich nur als Zeitstempel vorhanden sind, für die Ausgabe kann man das Datum dann mit date() formatiert ausgeben.
                Desweiteren wäre es leichter die Ausgabe auch formatiert zu handhaben, sprintf() ist ein simpler Weg.

                Wahrscheinlich wirst du, je nach dem wie die Daten ankommen, nicht mal Reguläre Ausdrücke brauchen.

                MfG
                bubble

        2. gudn tach!

          /[([a-z0-9-]+)]/i
          Damit wäre es sogar noch kürzer geschrieben ;)

          Wenn mich nicht alles täuscht, sogar:
          /[([\w\d-]+)]/

          vorsicht, damit sind locale-abhaengig umlaute oder aehnliches zeugs drin oder nicht. deshalb im zweifel besser \w vermeiden.

          prost
          seth

          1. Tach!

            Wenn mich nicht alles täuscht, sogar:
            /[([\w\d-]+)]/
            vorsicht, damit sind locale-abhaengig umlaute oder aehnliches zeugs drin oder nicht. deshalb im zweifel besser \w vermeiden.

            ... und stattdessen \p{L} oder eine angemessenere Variante nehmen: Unicode character properties.

            dedlfix.