Как мне остановить матч при первом появлении?

Мне нужно переварить некоторые 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} позволяет определить именованные подшаблоны, которые можно использовать позже, не сопоставляя ничего.

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