2013-03-18 24 views
6

Tôi không giỏi tìm kiếm tự động hóa đúng đắn của một regex, để tạo ra các biểu thức khác nhau, nhưng khi nói đến kịch bản trong PHP, nó trở thành đau trong mông của tôi. Tôi không thể đề xuất bản thân mình có thể viết một mẫu trong preg_match mà sẽ 'phù hợp' biểu thức như: 123-23-345 ... 123-34-456 .... 12-234-56 ..... Nó nên là 3 nhóm chữ số, trong đó mỗi nhóm, từng cá thể được sắp xếp từ trái sang phải, và mọi nhóm tiếp theo không có chữ số lớn hơn chữ số lớn nhất của nhóm trước đó. Điều này: 123-23-456 sẽ sai, vì 2 trong 23 nhỏ hơn 3 trong 123. 123-43-45 sai lần nữa vì 43 phải là 34 ...Regex và mẫu trong một preg_match - PHP để phù hợp với 123-23-345

Điều này sẽ giúp tôi xác thực một trường có thể chỉ có loại nội dung đó. Nó phải là một xác nhận regex không phải là một chức năng để phân tích cú pháp, tách ...

+6

Đây không thực sự là một vấn đề lý tưởng cho các cụm từ thông dụng. – Amber

+2

chắc chắn không phải là một công việc regex. regex là về các mẫu, và những gì bạn muốn làm liên quan đến ngữ nghĩa. –

+0

Bao lâu là mỗi nhóm? {1,3} hoặc không giới hạn? – HamZa

Trả lời

1

Thay vì chỉ sử dụng chức năng preg_, bạn cũng cần phải sử dụng một số điều kiện khác phù hợp.

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

Tương tự, bạn có thể so khớp các số trong các phần tương ứng, lặp lại tất cả các chữ và lại sử dụng cờ cho các giá trị không khớp.

Something như thế này:

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

Rõ ràng, đây không phải là tốt nhất/nhất được tối ưu hóa các giải pháp.

+0

Tôi nghĩ rằng mô hình từ preg_match biết nhiều hơn regex tự động hóa thường xuyên ... tôi đoán tôi sẽ phải phân tích nó theo cách này, cảm ơn. Bạn có thể vui lòng giải thích cho tôi mẫu, theo thẻ, như logic của tự động hóa .../^ (\ S +) \ - (\ S +) \ - (\ S +) $/tôi có được nó không nhưng không phải như thế nào .. – user1840192

+1

http://www.regular-expressions.info/ là một tài nguyên khá phong nha để học regex. – starshine531

2

Vâng, tôi sẽ không có giải pháp chỉ có regex. Vì vậy, ở đây tôi đã mã hóa hàm mà bạn cần:

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"; 
Các vấn đề liên quan