Сопоставить все, кроме переменной строки


Я смог сопоставить весь текст в строке, которая выглядит следующим образом:

[!--$element--]

Используя приведенное ниже регулярное выражение:

\[!--(.*?)]
Однако теперь я хочу сопоставить все, кроме приведенной выше строки, но не могу заставить ее работать. Я попытался использовать выражение not ^ и выражение look-ahead ?!, но, похоже, не могу его правильно понять.

Например,

Я хочу

This is an [!--$element--]

Превратиться в:

[!--$element--]

Я использую PHPs preg_replace() для удаления весь текст, который не является [--$element--]

Любые идеи, как я могу сделать так?

4   2   2014-07-30 02:15:32

4 ответа:

Группа захвата, (*SKIP)(*F) или разделение

Чтобы соответствовать этому, у нас есть несколько вариантов.

Вариант 1: с группами захвата

Это более длинный способ сделать это, но он будет работать во всех двигателях.
\[!--[^-]*--\]|((?:(?!\[!--[^-]*--\]).)+)

Нужные строки находятся в группе 1. В демонстрация регулярных выражений, посмотрите на снимки в правой панели .

Вариант 2: (*пропустить) (*F)

Это будет работать только в Perl и PCRE (и, следовательно, PHP). Оно напрямую соответствует строкам.

\[!--[^-]*--\](*SKIP)(*F)|(?:(?!\[!--[^-]*--\]).)+

В демонстрация регулярных выражений, смотрите совпадающие строки.

Вариант 3: Разделить

Матч все и Сплит - это две стороны одной монеты , поэтому мы можем использовать preg_split вместо preg_match_all. Разделяя строку, мы удаляем части, которые хотим исключить.

$element_regex = '~\[!--[^-]*--\]~';
$theText = preg_split($element_regex, $yourstring);

Объяснение

Эта задача является классическим случаем метода, описанного в этом вопросе для " regex-match a образец, исключая..."

Вариант 1. в варианте 1 левая сторона чередования | совпадает с полной [!--$element--]. Мы будем игнорировать эти матчи. Правая сторона совпадает и захватывает другой текст, и мы знаем, что это правые, потому что они не совпадают с выражением слева.

Вариант 2 . В Варианте 2 левая сторона чередования | соответствует полной [!--$element--] , после чего сознательно выходит из строя, после чего двигатель переходит в следующую позицию в строке. Правая сторона соответствует нужному вам слову this, и мы знаем, что это правильные слова, потому что они не были сопоставлены выражением слева.

Ссылка

Вместо замены текста, который вам не нужен, просто возьмите текст, который вы хотите:

preg_match_all('/\[!--(.*?)]/', $input, $matches);
$result = implode('', $matches[0]);

Демо

Используйте preg_replace с этим шаблоном Demo

preg_replace("/(.*)(\[!--.*?])(.?)/", "\1\3", $input_lines);

Обратите внимание, что я не использовал [!--(.*?)], потому что он также будет соответствовать элементам, отличным от [!--$element--], таким как [!--$element]

<?php
$text ='This is an [!--$element--]. Here is some other text';
preg_match_all('#(\[\!--.*--\])#',$text,$out);
print_r($out);
?>

А выход -

Array
(
    [0] => Array
        (
            [0] => [!--$element--]
        )

    [1] => Array
        (
            [0] => [!--$element--]
        )

)

Вот он-лайн демо-версия