Я пытаюсь сопоставить разметку с помощью регулярных выражений:
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]
в пределах []
, но он должен полностью игнорировать эту часть
С 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 пуста (но определена). Функция обратного вызова должна проверить это, чтобы узнать, какая ветвь завершается успешно, и вернуть соответствующую строку замены.
Других решений пока нет …