如何在第一次出现时停止比赛?

时间:2013-06-04 00:31:25

标签: ruby xml regex match bbcode

我需要用Ruby正则表达式消化一些bbcode。

我必须使用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]是nil而不是“References”。

如何分隔通常的bbcode标签之间的文本部分?

2 个答案:

答案 0 :(得分:8)

使用非贪婪的算子?,如下所示:

t=s.match(/[b](.*?)[/b]/m)

答案 1 :(得分:1)

如果您确定在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}允许定义以后可以使用而不匹配任何内容的命名子模式。