代码之家  ›  专栏  ›  技术社区  ›  Scott Chu

preg_中的regex匹配不匹配行注释源代码并捕获错误的子模式

  •  1
  • Scott Chu  · 技术社区  · 6 年前

    [注:为了更好地描述我的问题,我重写了我的帖子,感谢马里奥,我已经回答过了]

    我想把这些图案搭配起来( 也允许在两个 ):

    Connection variable = new DBConnection
    variable = new DBConnection
    

    但不匹配:

    //Connection variable = new DBConnection
    //variable = new DBConnection
    //    Connection variable = new DBConnection
    //    variable = new DBConnection
    

    最后捕获变量名。

    这是我的regexp

    #(?<!//)(?:\s*Connection\s+)+(.+?)\s*=\s*new\s+DBConnection#
    

    但不匹配示例列表中的最后两行仍然匹配。我怎样才能修好我的正则表达式?是因为消极的旁观者必须检查 紧接着 一些 定长字符串 只有?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Wiktor Stribiżew    6 年前

    您可以使用这两种方法之一。

    方法1: SKIP-FAIL regex

    你可以匹配所有以 // 跳过它们,只匹配其他上下文中的子字符串。

    '~^(\s*//.*)(*SKIP)(*F)|^(?:\s*Connection\s+)?(.+?)\s*=\s*new\s+DBConnection~m'
    

    regex demo

    PHP demo :

    $re = '~^(\s*//.*)(*SKIP)(*F)|^(?:\s*Connection\s+)?(.+?)\s*=\s*new\s+DBConnection~m';
    $str = "Connection variable = new DBConnection\n    variable = new DBConnection\n    //\n    //Connection variable = new DBConnection\n    //variable = new DBConnection\n    //    Connection variable = new DBConnection\n    //    variable = new DBConnection";
    if (preg_match_all($re, $str, $matches)) {
        print_r($matches[0]);
    }
    

    输出:

    Array
    (
        [0] => Connection variable = new DBConnection
        [1] =>     variable = new DBConnection
    )
    

    方法2:可选的捕获组和一些后处理

    在php pcre regex模式中,不能使用无限宽lookbehinds,这意味着不能用 * , + , *? , +? , ? , ? , {1,4} , {3,} 量词。此外,也不能使用嵌套交替。

    通常的解决方法是使用 可选捕获组 并在找到匹配项后检查其值。如果组值不为空,则表示匹配应为“失败”,丢弃,否则,获取所需的捕获。

    下面是一个正则表达式示例:

    '~^(\s*//)?(?:\s*Connection\s+)?(.+?)\s*=\s*new\s+DBConnection~m'
    

    regex demo :

    enter image description here

    绿色突出显示的子字符串是组1匹配项。我们可以这样在代码中检查它们:

    $result = "";                    // Result is empty
    if (preg_match($rx, $s, $m)) {   // Is there a match?
        if (empty($m[1])) {          // Is the match group #1 empty?
            $result = $m[0];         // If yes, we found a result
        }
    }                                // Else, result will stay empty
    

    PHP demo :

    $strs = ['Connection variable = new DBConnection', 'variable = new DBConnection', '//Connection variable = new DBConnection', '//variable = new DBConnection'];
    $rx = '~^(\s*//)?(?:\s*Connection\s+)?(.+?)\s*=\s*new\s+DBConnection~m';
    foreach ($strs as $s) {
        echo "$s:\n";
        if (preg_match($rx, $s, $m)) {
            if (empty($m[1])) {
                echo "FOUND:" . $m[0] . "\n--------------\n";
            }
        } else {
            echo "NOT FOUND\n--------------\n";
        }
    }
    

    输出:

    Connection variable = new DBConnection:
    FOUND:Connection variable = new DBConnection
    --------------
    variable = new DBConnection:
    FOUND:variable = new DBConnection
    --------------
    //Connection variable = new DBConnection:
    //variable = new DBConnection:
    

    同样的技术也可以用于 preg_replace_callback 如果你需要更换。