Захват ошибок компиляции регулярных выражений

Я пытаюсь настроить службу, похожую на rubular , но с PHP как языком, использующим семейство функций preg . Он примет входное регулярное выражение, тестовую строку и запустит preg_match() .

Как узнать, произошла ли ошибка компиляции (например: недопустимое регулярное выражение), и, если это так, какова была ошибка? Обычно он будет вызывать предупреждения типа:

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

pcre_last_error() здесь совершенно бесполезен, так как он будет возвращать 0 ( PREG_NO_ERROR ), если регулярное выражение не скомпилируется.

Один из вариантов, который я рассматриваю, – использовать буферизацию вывода для захвата предупреждения, но должен быть лучший способ.

Solutions Collecting From Web of "Захват ошибок компиляции регулярных выражений"

Лучшее, что вы можете сделать, это опустить сообщение об ошибке с @ , проверить возвращаемое значение и, если false , вызвать error_get_last .

Вы также можете написать свою собственную оболочку вокруг pcre_compile . Он получает указатели для хранения кодов ошибок и строк. Не должно быть слишком сложно; preg_match – это тонкая оболочка.

Вы можете легко проверить ошибки компиляции регулярных выражений в PHP, зарегистрировав собственный обработчик ошибок. Я написал тег регулярного выражения PHP, который обнаруживает ошибки компиляции регулярных выражений и сообщает их пользователю без отображения конфиденциальной информации, такой как имена файлов и номера строк. Ключевая часть здесь заключается в том, что пользовательский обработчик ошибок может улавливать ошибки компиляции регулярных выражений. Вам не нужно бросать исключение или ловить его. Остальное – удобная демонстрация.

Я использую set_error_handler () для регистрации функции, которая генерирует исключение ErrorException. Я поймаю исключение при запуске preg_match (), а затем использую информацию трассировки, чтобы убедиться, что исключение было выбрано из того же файла, строки и функции, из которых я запускаю preg_match () (если нет, ошибка или исключение было вызвано чем-то иначе как другой вызов функции в той же строке или у PHP заканчивается память). Затем я вывожу пользователю сообщение об ошибке.

Обратите внимание, что этот скрипт фактически выполняет функцию regex с помощью переменной функции. Введите ввод, регулярное выражение без ведущей и конечной косой черты и любые модификаторы отдельно.

Вот полный код:

 <!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>