Регулярное выражение: есть регулярное выражение внутри - PullRequest
1 голос
/ 20 декабря 2011

Я все глубже погружаюсь в темную сторону регулярного выражения.Мне нужно разобрать это:

{{word(a|b|c)|word$1}}
{{word(s?)|word$1}}
{{w(a|b|c)ord(s?)|w$1ord$2}}

Как вы могли заметить, это схема поиска и замены, содержащая регулярные выражения.Движок Викимедиа делает это очень хорошо, но я не мог найти, как он это делает: прямо здесь .

Мне просто нужно получить первую часть, а вторую - в две разделенные переменные,Например:

preg_match(REGEX, "{{word(a|b|c)|word$1}}", $result) // Applying REGEX on this
echo $result[1] // word(a|b|c)
echo $result[2] // word$1

Как бы вы поступили?Это как регулярное выражение в регулярном выражении, я полностью потерян ...

Ответы [ 3 ]

2 голосов
/ 20 декабря 2011

Вы можете сопоставить детали, используя что-то вроде:

{{((?:(?!}}).)+)\|([^|]+?)}}

Обратите внимание, что если вы разрешаете произвольное регулярное выражение PCRE, то можно создать несколько очень сложных и медленных шаблонов, возможно, допускающих простые DoS-атаки на ваш сайт.

1 голос
/ 20 декабря 2011

Это действительно зависит от того, насколько глубокой может быть вложенность, но вы можете просто разделить ее на |, стараясь не разделить ее на любые | в скобках.Вот простой способ, я полагаю:

$str = 'word(a|b|c)|word$1'; // Trim off the leading and trailing {{ and }}
$items = explode('|', $str);
$realItems = array();

for($i = 0; $i < count($items); $i++) {
    $realItem = $items[$i];
    while(substr_count($realItem, '(') > substr_count($realItem, ')')) {
        // Glue them together and skip one!
        $realItem .= '|' . $items[++$i];
    }

    $realItems[] = $realItem;
}

Теперь $realItems[] содержит ваши 2-4 ключевых значения, которые вы можете просто передать в preg_replace;он сделает всю работу за вас.

0 голосов
/ 20 декабря 2011

Это на самом деле не так сложно.

Дело в том, что строка замены будет содержать только экранированный |, то есть \|.

И для одного из этих очень немногих случаев, .* действительно будет здесь полезно.

Do: preg_match("^{{(.*)\|([^|]+(?:\\\|[^|]*)*)}}$", $result);, это должно делать то, что вы хотите.

Хитрость здесь заключается во второй группе: это опять-таки шаблон normal* (special normal*)*, где normal это [^|] (что угодно, кроме трубы), а special это \\\| (обратный слеш, за которым следует труба).

...