代码之家  ›  专栏  ›  技术社区  ›  NullUserException Mark Roddy

捕获正则表达式编译错误

  •  7
  • NullUserException Mark Roddy  · 技术社区  · 14 年前

    rubular ,但是使用PHP作为使用preg函数族的语言。它需要一个输入regex、一个测试字符串,然后运行 preg_match()

    如何找出是否发生了编译错误(例如:regex无效),如果是这种情况,错误是什么?通常它会发出如下警告:

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

    pcre_last_error() 在这里完全没有用,因为它将返回0( PREG_NO_ERROR

    我正在考虑的一个选择是使用输出缓冲来捕获警告,但必须有更好的方法。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Artefacto    14 年前

    您所能做的最好的事情就是用 @ ,检查返回值,如果 false error_get_last .

    你也可以写你自己的包装 pcre_compile . 它接收用于存储错误代码和字符串的指针。不应该太难; preg_match

        2
  •  0
  •   taz    13 年前

    通过注册自己的错误处理程序,可以轻松地检查PHP中的regex编译错误。我编写了一个PHP regex测试程序,它可以检测regex编译错误并向用户报告,而不显示文件名和行号等敏感信息。这里的关键部分是自定义错误处理程序可以捕获regex编译错误。您不必抛出或捕获异常。剩下的就是一个方便的演示。

    我使用set\u error\u handler()注册一个抛出ErrorException的函数。我在运行preg\u match()时捕获异常,然后使用跟踪信息验证异常是否是从运行preg\u 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>