Простой Wiki Parser и Link Autodetection

Я использую следующие функции:

function MakeLinks($source){ return preg_replace('!(((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)!i', '<a href="/1">$1</a>', $source); } function simpleWiki($text){ $text = preg_replace('/\[\[Image:(.*)\]\]/', '<a href="$1"><img src="$1" /></a>', $text); return $text; } 

Первый конвертирует http://example.com в ссылку http://example.com .

Вторая функция превращает строки, такие как [[Image:http://example.com/logo.png]] в изображение.

Теперь, если у меня есть текст

 $text = 'this is my image [[Image:http://example.com/logo.png]]'; 

и конвертировать его, как эта simpleWiki(makeLinks($text)) она выводит что-то похожее:

 this is my image <a href="url"><img src="<a href="url">url</a>"/></a> 

Как я могу это предотвратить? Как проверить, что URL-адрес не является частью конструкции [[Image:URL]] ?

Ваша непосредственная проблема может быть решена путем объединения двух выражений в один (с двумя альтернативами), а затем с использованием не очень хорошо известной, но очень мощной функции : preg_replace_callback() которая обрабатывает каждый случай отдельно за один проход через целевая строка:

 <?php // test.php 20110312_1200 $data = "[[Image:http://example.com/logo1.png]]\n". "http://example1.com\n". "[[Image:http://example.com/logo2.png]]\n". "http://example2.com\n"; $re = '!# Capture WikiImage URLs in $1 and other URLs in $2. # Either $1: WikiImage URL \[\[Image:(.*?)\]\] | # Or $2: Non-WikiImage URL. (((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+) !ixu'; $data = preg_replace_callback($re, '_my_callback', $data); // The callback function is called once for each // match found and is passed one parameter: $matches. function _my_callback($matches) { // Either $1 or $2 matched, but never both. if ($matches[1]) { // $1: WikiImage URL return '<a href="'. $matches[1] . '"><img src="'. $matches[1] .'" /></a>'; } else { // $2: Non-WikiImage URL. return '<a href="'. $matches[2] . '">'. $matches[2] .'</a>'; } } echo($data); ?> 

Этот скрипт реализует ваши два регулярных выражения и делает то, что вы просите. Обратите внимание, что я изменил жадную (.*) На (.*?) Ленивую версию, потому что жадная версия работает некорректно (она не может обрабатывать несколько WikiImages). Я также добавил модификатор 'u' в регулярное выражение (которое необходимо, когда шаблон содержит символы Unicode). Как вы можете видеть, функция обратного вызова preg очень эффективна. (Этот метод может быть использован для выполнения довольно тяжелого подъема, обработки текста).

Однако обратите внимание, что регулярное выражение, которое вы используете для выбора URL-адресов, может быть значительно улучшено. Ознакомьтесь со следующими ресурсами для получения дополнительной информации о URL-адресах «Связывание» (подсказка: есть куча «gotchas»):
Проблема с URL-адресами
Улучшенный либеральный, точный шаблон регулярных выражений для сопоставления URL-адресов
URL-ссылка (HTTP / FTP)

В своем MakeLinks добавьте это [^:"]{1} , см. Ниже:

 function MakeLinks($source){ return preg_replace('![^:"]{1}(((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)!i', '<a href="/1">$1</a>', $source); } 

Тогда только ссылка без «:» раньше (как в Image 🙂 будет преобразована. И используйте $text = simpleWiki(MakeLinks($text)); ,

EDIT: вы можете изменить это: preg_replace('![[:space:]](((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)[[:space:]]!i', '<a href="$1">$1</a>', $source);