Заменить текст между строками в php
Мне нужно найти все экземпляры двух строк и заменить весь текст, заключенный между ними. Например:
[LINK]mySite.com[NAME]Click to visit my site[ENDLINK]
Необходимо заменить на:
<a href="mySite.com">Click to visit my site</a>
Пока у меня есть следующее, которое работает:
if(stristr("$text","[LINK]") && stristr("$text","[ENDLINK]")):
$text = str_ireplace("[LINK]","\n<a href=\"" ,"$text");
$text = str_ireplace("[NAME]", "\" target=\"_self\"><u>", "$text");
$text = str_ireplace("[ENDLINK]","</u></a>","$text");
endif;
Тем не менее, он заменяет [NAME] во всех других пользовательских тегах, которые я использую, например, у меня также есть:
if(stristr("$text","[FILE]") && stristr("$text","[ENDFILE]")):
$text = str_ireplace("[FILE]","\n<a href=\"" ,"$text");
$text = str_ireplace("[NAME]", "\" target=\"_blank\"><u>", "$text");
$text = str_ireplace("[ENDFILE]","</u></a>","$text");
endif;
Как вы можете видеть, [FILE] использует target="_blank", а [LINK] использует target="_self", когда я использую приведенный выше скрипт, он заменяет все экземпляры [NAME] на "_blank".
Переименование тега [ИМЯ] не является жизнеспособным вариантом, поскольку тысячи записей уже используют его в базе данных, и пользователи привыкли использовать его как есть.
Есть ли простой способ заставить это работать?
2 ответа
$text = "[LINK]picture-large.jpg[NAME][IMAGE]picture-small.jpg[ENDIMAGE][ENDLINK] ... [LINK]mySite.com[NAME]Click to visit my site[endlink] lorem ipsum dolor sit amet ... [LINK]anothersite.com[name]Don't click here[ENDLINK] and here goes the file: [FILE]file.pdf[NAME]This is link to file[ENDFILE]";
function replaceFiles($match) {
return '<a href="'.$match[1].'" target="_blank"><u>'.$match[2].'</u></a>';
}
function replaceImages($match) {
return '<img src="'.$match[1].'" />';
}
function replaceLinks($match) {
return '<a href="'.$match[1].'" target="_self"><u>'.$match[2].'</u></a>';
}
$text = preg_replace_callback('/\[FILE\](.*?)\[NAME\](.*?)\[ENDFILE\]/i', 'replaceFiles', $text);
$text = preg_replace_callback('/\[IMAGE\](.*?)\[ENDIMAGE\]/i', 'replaceImages', $text);
$text = preg_replace_callback('/\[LINK\](.*?)\[NAME\](.*?)\[ENDLINK\]/i', 'replaceLinks', $text);
Это вернется, только если весь шаблон соответствует:
public function replaceLinks($text){
return preg_replace('/\[LINK](.*?)\[NAME](.*?)\[ENDLINK]/', "<a href='$1'>$2</a>", $text);
}
Прежде всего, он работает с использованием шаблона, который соответствует всему, а не только частям ссылки.
Вот пошаговое руководство по регулярному выражению (не буквально шаг за шагом о том, как работает механизм регулярных выражений до того, как вы клянетесь на регулярных выражений):
- Прямая косая черта используется, чтобы содержать выражение.
- Мы ставим
\
перед[
чтобы избежать этого, в противном случае он интерпретируется как начало класса символов. - Мы соответствуем буквальному
LINK]
, - Мы создаем группу захвата для любого персонажа
.
любое количество раз*
, но с ленивым модификатором?
, На это ссылаются$1
в строке замены. - Я не буду объяснять остальное, потому что это тот же процесс для остальной части строки.
Вот класс PHPUnit, который демонстрирует правильное поведение:
class Test extends PHPUnit_Framework_TestCase {
public function replaceLinks($text){
return preg_replace('/\[LINK](.*?)\[NAME](.*?)\[ENDLINK]/', "<a href='$1'>$2</a>", $text);
}
public function testCase1(){
// Must replace links
$input = "[LINK]mySite.com[NAME]Click to visit my site[ENDLINK]";
$output = $this->replaceLinks($input);
$expected = "<a href='mySite.com'>Click to visit my site</a>";
$this->assertEquals($expected, $output);
}
public function testCase2(){
// Must not replace files
$input = "[FILE]mySite.com[NAME]Click to visit my site[ENDFILE]";
$output = $this->replaceLinks($input);
$expected = "[FILE]mySite.com[NAME]Click to visit my site[ENDFILE]";
$this->assertEquals($expected, $output);
}
}