【问题标题】:How do I make match stop on first occurance?如何在第一次出现时停止比赛?
【发布时间】:2013-06-04 00:31:25
【问题描述】:

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

我必须使用 match 命令分隔元素,并使用正则表达式 /pattern/m 去除换行符。

比如我的bbcode在一个字符串中是:

s="[b]Title[/b] \n Article text \n [b]references[/b]"

然后我使用match 来分隔文本的各个部分,尤其是包含在[b][/b] 之间的Title 和References 部分:

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

我使用(..) 语法来捕获正则表达式中的字符串,并使用\ 来转义特殊的[] 字符。 /m 是去掉字符串中的换行符。

那么t[1] 包含:

"Title[/b] \n Artucle text \n [b]references"

而不是"Title"。因为匹配不会在[/b] 的第一次出现时停止。出于同样的原因,t[2] 是 nil 而不是“References”。

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

【问题讨论】:

    标签: ruby xml regex match bbcode


    【解决方案1】:

    像这样使用非贪心运算符?

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

    【讨论】:

    • “贪婪”意味着正则表达式尝试消耗尽可能多的输入。 “非贪”是相反的意思。 :-)
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-05-16
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 2014-12-04
      • 2012-07-03
      • 2012-12-15
      相关资源
      最近更新 更多