2010-08-21 22 views
6

मैं rubular जैसी सेवा स्थापित करने की कोशिश कर रहा हूं, लेकिन PHP के साथ फ़ंक्शन के प्रीग परिवार का उपयोग कर भाषा के रूप में। यह इनपुट रेगेक्स, एक टेस्ट स्ट्रिंग लेगा, और preg_match() चलाएगा।रेगेक्स संकलन त्रुटियों को कैप्चर करना

मैं कैसे पता लगा सकता हूं कि संकलन त्रुटि हुई है (उदाहरण: अवैध regex), और यदि ऐसा है, तो त्रुटि क्या थी? आम तौर पर ऐसा लगता है कि चेतावनी फेंक देगा:

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

pcre_last_error(), यहाँ पूरी तरह से बेकार है अगर regex संकलित करने के लिए विफल रहता है के बाद से यह 0 (PREG_NO_ERROR) वापस आ जाएगी।

एक विकल्प जो मैं विचार कर रहा हूं वह चेतावनी को पकड़ने के लिए आउटपुट बफरिंग का उपयोग करना है, लेकिन एक बेहतर तरीका होना चाहिए।

उत्तर

2

सबसे अच्छा आप कर सकते हैं त्रुटि संदेश @ के साथ त्रुटि संदेश को छोड़ना है, वापसी मूल्य की जांच करें और false, error_get_last पर कॉल करें।

आप pcre_compile के आसपास अपना खुद का रैपर भी लिख सकते हैं। यह त्रुटि कोड और तारों के भंडारण के लिए पॉइंटर्स प्राप्त करता है। बहुत मुश्किल नहीं होना चाहिए; preg_match एक पतली आवरण है।

+0

'error_get_last()' काफी अच्छा है :) – NullUserException

0

आप अपने स्वयं के त्रुटि हैंडलर को पंजीकृत करके आसानी से रेगेक्स संकलन त्रुटियों की जांच कर सकते हैं। मैंने एक PHP रेगेक्स परीक्षक लिखा है जो रेगेक्स संकलन त्रुटियों का पता लगाता है और फ़ाइल नामों और रेखा संख्याओं जैसे संवेदनशील जानकारी प्रदर्शित किए बिना उन्हें उपयोगकर्ता को रिपोर्ट करता है। यहां का मुख्य भाग यह है कि एक कस्टम त्रुटि हैंडलर regex संकलन त्रुटियों को जाल कर सकते हैं। आपको अपवाद फेंकना या पकड़ना नहीं है। बाकी एक सुविधाजनक प्रदर्शन है।

मैं error_error_handler() का उपयोग करता हूं जो एक त्रुटि अपवाद को फेंकने वाले फ़ंक्शन को पंजीकृत करने के लिए करता है। मैं preg_match() चलाते समय अपवाद को पकड़ता हूं, फिर ट्रेस जानकारी का उपयोग यह सत्यापित करने के लिए करता हूं कि अपवाद को उसी फ़ाइल, रेखा और फ़ंक्शन से निकाल दिया गया था जिसे मैं preg_match() से चलाता हूं (यदि नहीं, तो कोई त्रुटि या अपवाद कुछ होता है अन्यथा एक ही पंक्ति या PHP में स्मृति से बाहर चलने वाले एक अलग फ़ंक्शन कॉल की तरह)। फिर मैं उपयोगकर्ता को केवल त्रुटि संदेश आउटपुट करता हूं।

ध्यान दें कि यह स्क्रिप्ट वास्तव में एक परिवर्तनीय फ़ंक्शन का उपयोग कर रेगेक्स फ़ंक्शन चलाती है। इनपुट, रेगेक्स को अग्रणी और पिछला स्लैश के बिना, और किसी भी संशोधक को अलग से दर्ज करें।

यहाँ पूर्ण कोड है:

<!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> 
संबंधित मुद्दे