Вопрос по regex, php – Почему мое регулярное выражение PHP, которое разбирает ссылки Markdown, не работает?

6
<code>$pattern = "/\[(.*?)\]\((.*?)\)/i";
$replace = "<a href=\"$2\" rel=\"nofollow\">$1</a>";
$text = "blah blah [LINK1](http://example.com) blah [LINK2](http://sub.example.com/) blah blah ?";
echo preg_replace($pattern, $replace, $text);
</code>

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

<code>$text = "blah blah [LINK1] (http://example.com) blah [LINK2](http://sub.example.com/) blah blah ?";
</code>

У меня такое чувство, что это ломкая звезда, которая его ломает, но я не знаю, как еще найти повторяющиеся звенья.

Это. Мне нужна только базовая функция ссылки без необходимости идентификатора и заголовка. user1070125
Это какой-то анализатор Markdown? Если это так, почему вы не используете уже существующий? Gumbo

Ваш Ответ

2   ответа
7

все, что вам нужно сделать, это также сопоставить любое количество пробелов между ними, например:

/\[([^]]*)\] *\(([^)]*)\)/i

Объяснение:

\[             # Matches the opening square bracket (escaped)
([^]]*)        # Captures any number of characters that aren't close square brackets
\]             # Match close square bracket (escaped)
 *             # Match any number of spaces
\(             # Match the opening bracket (escaped)
([^)]*)        # Captures any number of characters that aren't close brackets
\)             # Match the close bracket (escaped)

Обоснование:

Я, наверное, должен оправдать, что причина, по которой я изменил вашу.*? в[^]]*

Вторая версия более эффективна, потому что она не требует огромного количества возвратов,.*? делает. Кроме того, после открытия[ встречается,.*?  Версия будет продолжать поиск до тех пор, пока не найдет совпадение, а не потерпит неудачу, если она не будет тегом, как хотелось бы. Например, если мы сопоставим выражение с помощью.*? против:

Sad face :[ blah [LINK1](http://sub.example.com/) blah

это будет соответствовать

[ blah [LINK1]

а также

http://sub.example.com/

С использованием[^]]* Подход будет означать, что вход соответствует правильно.

Я также добавил обоснование того, почему я изменился.*? в[^]]*
Я понял вашу точку зрения, но [^]] * соответствует завершению] и вашему & quot; грустному лицу & quot; пример все равно не удастся. user1070125
Не соответствует URL с такими символами какen.wikipedia.org/wiki/Toast_(computing)
У этого есть опечатка, но я не могу это исправить, поскольку я не уверен, как это должно работать. user1070125
Вы правы, я исправил опечатку и добавил объяснение для вас
0

Попробуй это:

$pattern = "/\[(.*?)\]\s?\((.*?)\)/i";

\s? добавлено между\[(.*?)\] а также\((.*?)\)

Это так или иначе работает, заботясь об одном единственном месте. Я думаю, что лучше будет требовать строгой разметки и игнорировать все остальное (вывод как есть). user1070125

Похожие вопросы