регулярное выражение в preg_match, чтобы НЕ соответствовать исходный код комментария строки и захватить неправильный подшаблон - PullRequest
0 голосов
/ 08 июня 2018

[ПРИМЕЧАНИЕ: я переписываю свой пост, чтобы лучше описать свой вопрос, благодаря моей благодарности Марио, и я ответила ранее.]

Я хочу сопоставить эти шаблоны ( а также разрешить количество пробелов в интервале ):

Connection variable = new DBConnection
variable = new DBConnection

, но НЕ совпадают:

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

и, наконец, захватить имя переменной.

Это мое регулярное выражение

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

, но последние две строки в списке примеров несоответствий по-прежнему совпадают.Как я могу исправить свое регулярное выражение?Это потому, что отрицательный взгляд назад должен проверять вещи непосредственно перед некоторой строкой фиксированной длины * только 1021 *?

1 Ответ

0 голосов
/ 13 июня 2018

Вы можете использовать один из двух подходов.

Подход 1: Регулярное выражение SKIP-FAIL

Вы можете сопоставить все строки, начинающиеся с //, и пропуститьи соответствуют вашим подстрокам в других контекстах.

'~^(\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 вы не можете использовать шаблоны просмотра бесконечной ширины, означающие шаблонывнутри нельзя количественно определить с помощью *, +, *?, +?, ?, ?, {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 демо :

$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, если вам нужно заменить.

...