Как преобразовать тег url bbcode в гиперссылку html, используя значения тега bbcode?

Как я могу преобразовать тег [url] в bbcode в тег <a> с атрибутом href и текстом между открывающим и закрывающим тегами?

Вот несколько примеров строк:

[url]https://any.com/any[/url]

[URL = "https://any.com/any?any=333"]text text[/URL]

[url]http://www.any.com/any?any=44#sss[/url]

* Обратите внимание, что подстрока в двойных кавычках в открывающем теге [url] является необязательной и влияет на желаемый результат ...

Я пробовал этот шаблон:

(?:\[url = "(https?://(?:www)?.+?)\]|\[url\](https?://(?:www)?.+\[)) 
\[url = "(https?://(?:www\.)?.+?)\]|\[url\](https?://(?:www\.)?.+)\[/url\]
\[url = "(https?://(?:www\.)?.+)"\]|\[url\](https?://(?:www\.)?.+)\[/url\]

с чем-то вроде:

$pattern ='##i';
$text = preg_replace($pattern,'',$text);

Мой желаемый результат из приведенных выше тегов URL-адреса bbcode должен быть:

<a href = "https://any.com/any">https://any.com/any</a>

<a href = "https://any.com/any?any=333">text text</a>

<a href = "http://www.any.com/any?any=44#sss">http://www.any.com/any?any=44#sss</a>

Другими словами, если URL-адрес находится в части открывающего тега [url], заключенной в двойные кавычки, используйте это значение в качестве значения href и сохраните innerHTML тега [url] в качестве innerHTML сгенерированного тега <a>.

Если URL-адрес не заключен в двойные кавычки, но находится между открывающим и закрывающим тегами [url], используйте это значение как в качестве значения href, так и в качестве внутреннего HTML-кода <a>.

Связанный: stackoverflow.com/q/15998847/2943403stackoverflow.com/q/9900385/2943403

mickmackusa 06.05.2018 12:20
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
1
1 189
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы могли бы использовать

(?i)\[url(?| = "(?P<url>[^"]+)|\](?P<url>[^][]+))

См. демо на regex101.com.


Broken down:
(?i)                   # case insensitive
\[url                  # [url
(?|                    # branch reset
     = "(?P<url>[^"]+)   # either  = "..."
    |                  # or
    \](?P<url>[^][]+)  # ]...[/url]
)

В любом случае вам понадобится группа "url".

Это не сохраняет innerHTML тега bbcode.

mickmackusa 06.05.2018 14:12

@mickmackusa: это можно сделать, если вы включите атрибут url дважды в группу захвата: regex101.com/r/b0UVWh/2

Casimir et Hippolyte 07.05.2018 02:41

@Casimir умная игра.

mickmackusa 07.05.2018 02:43
Ответ принят как подходящий

UPDATE: Casimir's commented solution is more direct/clean.

Код: (Демо) (Демонстрация паттернов)

echo preg_replace('~\[url(?|]((https?://[^[]+))|(?: = "(https?://[^"]+)")](.+?))\[/url]~i', '<a href=\"$1\">$2</a>', $bbcode);

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

Вот немного расширенная вариация узора, который учитывает одинарное цитирование и отсутствие цитирования.


(Начало предыдущего решения)

Используя preg_match_callback(), вы можете определить, был ли указан URL-адрес внутри открывающего тега [url] - и в этом случае вы захотите сохранить текст, расположенный между открывающим и закрывающим тегами.

Если текст между тегами ЯВЛЯЕТСЯ URL-адресом, вы используете его в обоих местах в строке тега <a>.

Недействительные строки не будут преобразованы.

Код: (Демо) (Демонстрация паттернов).

$bbcodes = [
    '[URL]www.no.http.example.com[/URL]',
    '[url]https://any.com/any[/url]',
    '[url = "nourl"]nourl[/url]',
    '[URL = "https://any.com/any?any=333"]text text[/URL]',
    '[url = "http://www.emptyTEXT.com"][/url]',
    '[url]http://www.any.com/any?any=44#sss[/url]',
    '[url = "https://conflictinglink"]http://differenturl[/url]'
];

foreach ($bbcodes as $bbcode) {
    echo preg_replace_callback('~\[url(?:](https?://[^[]+)|(?: = "(https?://[^"]+)")](.+?))\[/url]~i',
                          function($m) {
                              if (isset($m[2])) {
                                  return "<a href=\"{$m[2]}\">{$m[3]}</a>";
                              }
                              return "<a href=\"{$m[1]}\">{$m[1]}</a>";
                          },
                          $bbcode);
    echo "\n---\n";
}

Выход:

[URL]www.no.http.example.com[/URL]
---
<a href = "https://any.com/any">https://any.com/any</a>
---
[url = "nourl"]nourl[/url]
---
<a href = "https://any.com/any?any=333">text text</a>
---
[url = "http://www.emptyTEXT.com"][/url]
---
<a href = "http://www.any.com/any?any=44#sss">http://www.any.com/any?any=44#sss</a>
---
<a href = "https://conflictinglink">http://differenturl</a>
---

Разбивка паттернов:

~                    #start of pattern delimiter
\[url                #match literally [url
(?:                  #start non-capturing group #1
  ]                  #match literally ]
  (https?://[^[]+)   #match and store as Capture Group #1 http , an optional s , colon , two forward slashes, then one or more non-opening square brackets (since valid href values cannot have square brackets)
  |                  #or
  (?:                #start non-capturing group #2
     = "               #match literally  = "
    (https?://[^"]+) #match and store as Capture Group #2 (same logic as Capture Group #1)
    "                #match literally "
  )                  #end non-capturing group #2
  ]                  #match literally ]
  (.+?)              #match (lazily) and store as Capture Group #3 one or more characters (this is the innerHTML component)
)                    #end non-capturing group #1
\[/url]              #match literally [/url]
~                    #end of pattern delimiter

Функция обратного вызова оценивает элементы в массиве Спички ($m) и условно генерирует и возвращает желаемый результат. Если есть какие-либо совпадения, вывод будет содержать:

array(
    0 => [the fullstring match]
    1 => [the url of a bbcode tag that does not have a quoted url]
)

или же

array(
    0 => [the fullstring match]
    1 => ''  // <-- empty string
    2 => [the quoted url of the bbcode tag]
    3 => [the text between the opening an closing bbcode tags]
)

как я могу сделать это регулярное выражение regex101.com этот код PHP 3v4l.org/kY1eb resut <iframe width = "560" height = "315" src = "youtube.com/embed/Z7Oc8QaM5VU">https://www.youtube.com/‌…>" frameborder = "0"> </iframe> положить я хочу <iframe width = "560 "height = " 315 "src = " youtube.com/embed/Z7Oc8QaM5VU "> frameborder = " 0 "> </iframe>

user1388167 07.05.2018 11:46

Это нетривиальная просьба. Вы, безусловно, должны стремиться достичь желаемого результата с помощью одного рисунка. Это может дать вам некоторую необходимую информацию: stackoverflow.com/a/48968340/2943403 Продолжайте пытаться решить проблему самостоятельно. Подобные проблемы делают вас лучшим разработчиком. Скажите себе, что вы можете это сделать, и продолжайте. Когда вы улучшили свой сниппет, но застряли на каком-то конкретном моменте, вы можете задать новый вопрос. Сообщество здесь очень талантливое.

mickmackusa 07.05.2018 12:33

P.s. если вы хотите сопоставить буквальную точку, например www., вы должны экранировать точку, как эта \.. Модификатор шаблона s (между # и i) заставляет точки «любой символ» также соответствовать символам новой строки - функция, которая, как мне кажется, не требуется для вашего шаблона.

mickmackusa 07.05.2018 13:52

@Hosam вот мое быстрое / грязное / необъяснимое решение: 3v4l.org/aUaYl

mickmackusa 07.05.2018 14:31

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