Заменить текст между строками в 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);
}

Прежде всего, он работает с использованием шаблона, который соответствует всему, а не только частям ссылки.

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

  1. Прямая косая черта используется, чтобы содержать выражение.
  2. Мы ставим \ перед [ чтобы избежать этого, в противном случае он интерпретируется как начало класса символов.
  3. Мы соответствуем буквальному LINK],
  4. Мы создаем группу захвата для любого персонажа .любое количество раз *, но с ленивым модификатором ?, На это ссылаются $1 в строке замены.
  5. Я не буду объяснять остальное, потому что это тот же процесс для остальной части строки.

Вот класс 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);
  }

}
Другие вопросы по тегам