Как мне остановить матч при первом появлении?
Мне нужно переварить некоторые bbcode с регулярным выражением Ruby.
Я должен разграничить элементы с match
команда и использовать регулярное выражение /pattern/m
избавиться от новых строк.
Например, мой bbcode в строке:
s="[b]Title[/b] \n Article text \n [b]references[/b]"
Тогда я использую match
разделить части текста, особенно заголовок и ссылки, которые заключены между [b]
а также [/b]
:
t=s.match(/\[b\](.*)\[\/b\]/m)
я использую (..)
синтаксис, чтобы поймать строку в регулярном выражении, и я использую \
избежать особого [
а также ]
персонажи. /m
это избавиться от новых строк в строке.
затем t[1]
содержит:
"Title[/b] \n Artucle text \n [b]references"
вместо "Title"
, потому что матч не останавливается при первом появлении [/b]
, А также t[2]
ноль вместо "Ссылки" по той же причине.
Как я могу разделить текстовые части, заключенные между обычными тегами bbcode?
2 ответа
Используйте не жадный оператор ?
как это:
t=s.match(/[b](.*?)[/b]/m)
Если вы уверены, что не встретите открывающие квадратные скобки между тегами bbcode, вы можете использовать класс символов, который исключает их:
t=s.match(/\[b\]([^\[]*)\[\/b\]/)
Но если ваш [b]
теги могут содержать другие теги, вам нужно использовать рекурсивный шаблон:
t=s.match(/(?x)
# definitions
(?<tag> \[ (?<name> \w++ ) [^\]]* \]
(?> [^\[]+ | \g<tag> )*
\[\/\g<name>\]
){0}
# main pattern
\[b\] (?<content> (?> [^\[]+ | \g<tag> )* ) \[\/b\]
/)
И если вам приходится иметь дело с самозакрывающимися тегами:
t=s.match(/(?x)
# definitions
(?<self> \[ (?:img|hr)\b [^\]]* \] ){0}
(?<tag> \[ (?<name> \w++ ) [^\]]* \]
(?> [^\[]+ | \g<self> | \g<tag> )*
\[\/\g<name>\]
){0}
# main pattern
\[b\] (?<content> (?> [^\[]+ | \g<self> | \g<tag> )* ) \[\/b\]
/)
Обратите внимание {0}
позволяет определить именованные подшаблоны, которые можно использовать позже, не сопоставляя ничего.