Regex: игнорирование совпадения с двумя скобками

Я пытаюсь сопоставить разметку с помощью регулярных выражений:

1. thats an [www.external.com External Link], as you can see
2. thats an [[Internal Link]], as you can see

Это должно привести к

1. thats an [External Link](www.external.com), as you can see
2. thats an [Internal Link](wiki.com/Internal Link), as you can see

Оба они прекрасно работают с этим preg_replaces:

1. $line = preg_replace("/(\[)(.*?)( )(.*)(\])/", "[$4]($2)", $line);
2. $line = preg_replace("/(\[\[)(.*)(\]\])/",   "[$2](wiki.com/$2)", $line);

Но они мешают друг другу, так что использование заменяет одно за другим, возвращает неприятные результаты. Поэтому я пытаюсь игнорировать в одном из матчей другой. Я попытался заменить первое регулярное выражение на это:

([^\[]{0,})(\[)([^\[]{1,})( )(.*)(])

Следует проверить, если есть только один [ и символ после и до не является [, Но его по-прежнему соответствует [Internal Link] в пределах [], но он должен полностью игнорировать эту часть

0

Решение

С preg_replace_callback Вы можете построить шаблон для обработки двух случаев и для определения условной замены в функции обратного вызова. Таким образом, строка анализируется только один раз.

$str =  <<<'EOD'
1. thats an [www.external.com External Link], as you can see
2. thats an [[Internal Link]], as you can see
EOD;

$domain = 'wiki.com';
$pattern = '~\[(?:\[([^]]+)]|([^] ]+) ([^]]+))]~';

$str = preg_replace_callback($pattern, function ($m) use ($domain) {
return empty($m[1]) ? "[$m[3]]($m[2])" : "[$m[1]]($domain/$m[1])";
}, $str);

echo $str;

Шаблон использует чередование (?: xxx | yyy), Первая ветвь описывает внутренние ссылки, а вторая — внешние.

Когда вторая ветвь успешна, первая группа захвата 1 пуста (но определена). Функция обратного вызова должна проверить это, чтобы узнать, какая ветвь завершается успешно, и вернуть соответствующую строку замены.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]