2013-03-18 14 views
6

Non sono molto bravo a trovare la giusta automazione di una regex, per generare espressioni diverse, ma quando si tratta di script in PHP, diventa un dolore nel mio culo. Non riesco a dimostrarmi in grado di scrivere un modello in preg_match che si adatti ad espressioni come: 123-23-345 ... 123-34-456 .... 12-234-56 ..... Dovrebbe essere 3 gruppi di cifre, in cui ogni gruppo, individualmente è ordinato da sinistra a destra, e ogni gruppo successivo non ha una cifra più grande della cifra più grande del gruppo precedente. Questo: 123-23-456 sarebbe sbagliato, poiché 2 su 23 è più piccolo di 3 su 123. 123-43-45 è di nuovo sbagliato perché 43 dovrebbe essere 34 ...Regex e pattern in un preg_match - PHP per adattarsi 123-23-345

Questo dovrebbe aiutarmi a convalidare un campo che potrebbe avere solo quel tipo di contenuto. Dovrebbe essere una convalida regex non una funzione per l'analisi, la divisione ...

+6

Questo non è davvero un problema ideale per le espressioni regolari. – Amber

+2

sicuramente non è un lavoro regex. regex riguarda i pattern e ciò che vuoi fare riguarda la semantica. –

+0

Quanto dura ogni gruppo? {1,3} o illimitato? – HamZa

risposta

1

Invece di utilizzare solo la funzione preg_, è necessario utilizzare anche altre condizioni corrispondenti.

<?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"; 
?> 

Allo stesso modo, è possibile abbinare i numeri in rispettive sezioni, iterare su tutti i letterali e di nuovo utilizzare il flag per i valori non-matching.

Qualcosa di simile a questo:

<?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"; 
?> 

Ovviamente, questo non è il migliore/più ottimizzata della soluzione.

+0

Ho pensato che i pattern di preg_match sapessero più della normale regex dell'automazione ... credo che dovrò analizzarlo in questo modo, grazie. Puoi spiegarmi il modello, per tag, come logica dell'automazione .../^ (\ S +) \ - (\ S +) \ - (\ S +) $/Ho capito cosa fa ma non come .. – user1840192

+1

http://www.regular-expressions.info/ è una risorsa abbastanza decente per l'apprendimento delle espressioni regolari. – starshine531

2

Bene, non ci sarà alcuna soluzione per l'espressione regolare, credo. Così qui ho codificato la funzione è necessario:

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";