2013-03-18 3 views
6

Ich bin nicht sehr gut darin, die richtige Automatisierung einer Regex zu finden, um verschiedene Ausdrucke zu generieren, aber wenn dies zum Skripten in PHP kommt, wird es zu einem Schmerz in meinem Arsch. Ich kann mir selbst nicht beweisen, dass ich ein Muster in preg_match schreiben kann, das Ausdrücke wie 12323-23-345 ... 123-34-456 ... 12-234-56 "passt" 3 Gruppen von Ziffern, wobei jede Gruppe einzeln von links nach rechts sortiert wird und jede nächste Gruppe keine Ziffer größer als die größte Ziffer der vorherigen Gruppe hat. Dies: 123-23-456 wäre falsch, wie 2 in 23 ist kleiner als 3 in 123. 123-43-45 ist wieder falsch, weil 43 34 sein sollte ...Regex und Muster in einem preg_match - PHP passt 123-23-345

Dies sollte mir helfen, ein Feld zu validieren darf nur diese Art von Inhalt haben. Es sollte eine Regex-Validierung sein, keine Funktion zum Analysieren, Teilen ...

+6

Dies ist nicht wirklich ein ideales Problem für reguläre Ausdrücke. – Amber

+2

definitiv keine Regex-Arbeit. regex handelt von Mustern, und was Sie tun wollen, beinhaltet Semantik. –

+0

Wie lange ist jede Gruppe? {1,3} oder unbegrenzt? – HamZa

Antwort

1

Anstatt nur die preg_-Funktion zu verwenden, müssten Sie auch eine andere Bedingung verwenden, die zutrifft.

<?php 
    $str = "123-34-456"; 
    preg_match("/^.*?(\d)\-(\d).*?(\d)\-(\d)/", $str, $matches); 
    $flag = true; 
    if($matches[2] < $matches[1]) 
     $flag = false; 
    if($matches[4] < $matches[3]) 
     $flag = false; 
    echo (!$flag) ? "ERROR" : "NO ERROR"; 
?> 

Ebenso können Sie die Zahlen in jeweiligen Abschnitten entsprechen, durchlaufen alle Literale und wieder die Flagge benutzen für nicht-Matching-Werten.

Etwas wie folgt aus:

<?php 
    $str = "132-34-456"; 
    preg_match("/^(\S+)\-(\S+)\-(\S+)$/", $str, $matches); 
    $flag = true; 
    for($i = 0; $i < strlen($matches[1]) - 1; $i++) { 
     if($matches[1][$i+1] < $matches[1][$i]) { 
      $flag = false; 
      break; 
     } 
    } 
    for($i = 0; $i < strlen($matches[2]) - 1; $i++) { 
     if($matches[2][$i+1] < $matches[2][$i]) { 
      $flag = false; 
      break; 
     } 
    } 
    for($i = 0; $i < strlen($matches[3]) - 1; $i++) { 
     if($matches[3][$i+1] < $matches[3][$i]) { 
      $flag = false; 
      break; 
     } 
    } 
    echo (!$flag) ? "ERROR" : "NO ERROR"; 
?> 

Offensichtlich ist dies nicht die beste/optimierte der Lösung.

+0

Ich dachte, Patterns von preg_match wüssten mehr als reguläre Automation Regex ... Ich denke, ich muss es auf diese Weise analysieren, danke. Können Sie mir bitte das Muster erklären, durch Tags, als die Logik der Automatisierung .../^ (\ S +) \ - (\ S +) \ - (\ S +) $/ich habe, was es tut, aber nicht wie .. – user1840192

+1

http://www.regular-expressions.info/ ist eine ziemlich gute Ressource zum Lernen von Regex. – starshine531

2

Nun, es wird keine Regex-only-Lösung geben, denke ich. Also hier codiert ich die Funktion, die Sie brauchen:

function isValidDigitExpression($string) { 
    $flag = preg_match('/^(\d+)\-(\d+)\-(\d+)$/', $string, $matches); 
    if (!$flag) return false; 

    // Check correct sorting by splitting digit string to array 
    for ($i = 1; $i <= 3; $i++) { 
     $block[$i] = str_split($matches[$i]); 
     $compare = $block[$i]; 
     sort($compare); 
     if ($compare != $block[$i]) return false; 
    } 

    // Compare Min and Max digits of neighboring digit blocks 
    return (max($block[1]) <= min($block[2]) and max($block[2]) <= min($block[3])); 
} 

$string = "123-34-356"; // Failure, because 3 < 4 comparing Block 2 and Block 3 
echo isValidDigitExpression($string) ? "SUCCESS" : "FAILURE";