2010-08-21 34 views
6

rubular'a benzer bir hizmet kurmaya çalışıyorum, ancak PHP, preg ailesi işlevlerini kullanarak dil olarak. Bir giriş regex'i, bir test dizesi alır ve preg_match()'u çalıştırır.Normal ifade derleme hataları

Derleme hatasının olup olmadığını nasıl öğrenebilirim (örneğin: geçersiz normal ifade) ve eğer durum buysa, hata neydi? Normalde gibi uyarılar atacağım: regex derlemek başarısız olursa 0 (PREG_NO_ERROR) dönecektir beri

Warning: preg_match() [function.preg-match]: Compilation failed: missing) at offset x in ****** on line y 

pcre_last_error(), burada tamamen işe yaramaz.

Gözden geçirmeyi düşündüğüm bir seçenek, uyarıyı yakalamak için çıktı arabellek kullanmaktır, ancak daha iyi bir yolu olmalı.

cevap

2

Yapabileceğiniz en iyi şey, hata iletisini @ ile atlamak, dönüş değerini ve false ise error_get_last numaralı telefonu aramaktır.

Ayrıca kendi ambalajınızı pcre_compile yazabilirsiniz. Hata kodları ve dizgileri saklamak için işaretçiler alır. Çok zor olmamalı; preg_match, ince bir sarıcıdır.

+0

'error_get_last()' yeterince iyi :) – NullUserException

0

Kendi hata işleyicinizi kaydederek PHP'deki normal ifade derlemelerini kolayca kontrol edebilirsiniz. Regex derleme hatalarını algılayan ve dosya isimleri ve satır numaraları gibi hassas bilgileri göstermeden bunları kullanıcıya bildiren bir PHP regex yazıcısı yazdım. Buradaki önemli kısım, özel bir hata işleyicisinin normal ifade derleme hatalarını yakalayabilmesidir. İstisna atmak ya da yakalamak zorunda değilsiniz. Gerisi uygun bir gösteri.

Bir ErrorException atanan bir işlevi kaydetmek için set_error_handler() kullanıyorum. Preg_match() işlevini çalıştırırken istisnayı yakalarım, sonra da özel durumun aynı dosyadan, satırdan ve preg_match() işlevinden çalıştırdığım işlevden atıldığını doğrulamak için izleme bilgilerini kullanın (eğer değilse, bir hata veya istisna bir şeyden kaynaklandıysa) Aynı satırda farklı bir işlev çağrısı veya PHP bellek dışında çalışan gibi). Sonra sadece hata mesajını kullanıcıya gönderirim.

Bu komut dosyasının aslında bir değişken işlevi kullanarak normal ifade işlevini çalıştırdığını unutmayın. Girdi, ön ve arka eğik çizgi olmadan regex ve herhangi bir değiştirici ayrı ayrı girin. İşte

tam kodudur:

<!DOCTYPE html> 
<html> 
<head> 
    <title>Test</title> 
    <style type="text/css"> 
     body { 
      font-family: monospace; 
     } 

     input[type=text], textarea { 
      letter-spacing: .25em; 
      font-weight: bold; 
      font-size: larger; 
     } 

     textarea { 
      width: 100%; 
      height: 25%; 
     } 

     fieldset { 
      display: inline; 
     } 

     .error { 
      color: red; 
     } 
    </style> 
</head> 
<body onload="document.getElementById('patterninput').focus();"> 
    <?php 
     // Translate old-style PHP errors to OO approach 
     // http://www.php.net/manual/en/class.errorexception.php 
     function testRegexErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) { 
      throw new ErrorException($errstr, 0, $errno, $errfile, $errline); 
     } 

     $pattern = isset($_REQUEST["pattern"]) ? $_REQUEST["pattern"] : ""; 
     $mods = isset($_REQUEST["mods"]) ? $_REQUEST["mods"] : ""; 
     $input = isset($_REQUEST["input"]) ? $_REQUEST["input"] : ""; 

     $regex = "/$pattern/$mods"; 
     $fns = array("match" => "preg_match", "matchall" => "preg_match_all"); 
     $fnKey = isset($_REQUEST["function"]) ? $_REQUEST["function"] : "matchall"; 
     $fn = isset($fns[$fnKey]) ? $fns[$fnKey] : "preg_match_all"; 

     try { 
      set_error_handler("testRegexErrorHandler"); 
      $result = $fn($regex, $input, $matches); 
     } catch (Exception $ex) { 
      // $ex is used later 
     } 
     restore_error_handler(); 
    ?> 
    <form action="" method="post"> 
     <input type="text" size="100" id="patterninput" name="pattern" value="<?php echo htmlspecialchars($pattern); ?>" placeholder="Pattern" /> 
     <input type="text" size="10" name="mods" value="<?php echo htmlspecialchars($mods); ?>" placeholder="Modifiers" /> 
     <fieldset><legend>Function</legend> 
      <label for="fnmatch">preg_match()</label><input type="radio" name="function" value="match" id="fnmatch" <?php echo $fnKey == "match" ? "checked" : ""; ?> /> 
      <label for="fnmatchall">preg_match_all()</label><input type="radio" name="function" value="matchall" id="fnmatchall" <?php echo $fnKey == "matchall" ? "checked" : ""; ?> /> 
     </fieldset> 
     <input type="submit" name="submit" /> 
     <textarea name="input" rows="10" placeholder="Input"><?php echo htmlspecialchars($input); ?></textarea> 
    </form> 
    <br/> 
<?php 
if(isset($ex)) { 
    $trace = $ex->getTrace(); 
    if(is_array($trace) && isset($trace[1]) && is_array($trace[1])) { 
     $errFn = isset($trace[1]["function"]) ? $trace[1]["function"] : ""; 
     $errLine = isset($trace[1]["line"]) ? $trace[1]["line"] : ""; 
     $errFile = isset($trace[1]["file"]) ? $trace[1]["file"] : ""; 

     if($errFn != "" && $errFn == $fn && $errLine != "" && $errLine == $ex->getLine() && $errFile != "" && $errFile == $ex->getFile() && get_class($ex) == "ErrorException") { 
      $regexErr = true; 
     } 
    } 

    if(empty($regexErr)) { 
     throw $ex; 
    } else { 
     echo "<p class=\"error\">The following error has occurred and is probably an error in your regex syntax:<br/>" .htmlspecialchars($ex->getMessage()) ."</p>\n\n"; 
    } 
} 

// result will be unset if error or exception thrown by regex function 
// such as if expression is syntactically invalid 
if(isset($_REQUEST["submit"]) && isset($result)) { 
    echo "Result: $result<br/>\n"; 
    echo "Matches:<pre>" .htmlspecialchars(print_r($matches, true)) ."</pre>\n\n"; 
} 
?> 
</body> 
</html>