代码之家  ›  专栏  ›  技术社区  ›  Ben S

是否可以将正则表达式快捷方式转换为匹配?

  •  0
  • Ben S  · 技术社区  · 15 年前

    我有一些正则表达式是针对非常长的字符串运行的。然而,字符串中与re有关的唯一部分就在开头附近。大多数研究结果类似于:

    \\s+?(\\w+?).*
    

    res在开始处捕获了几个组,而不关心字符串的其余部分是什么。出于性能原因,有没有一种方法可以让重新引擎避免查看终止所消耗的所有字符? .* ?

    注:带有res的应用程序是使用 java.regex 类。

    编辑: 例如,我有以下几点:

    .*?id="number"[^>]*?>([^<]+?).*
    

    它运行在存储为 StringBuilder 标签与 id="number" 总是在HTML文件的开头附近。

    6 回复  |  直到 15 年前
        1
  •  6
  •   Greg Hewgill    15 年前

    当使用java.util.regex类时,有许多方法可以与给定的字符串匹配。 Matcher.matches 总是与 整体 输入字符串。 Matcher.find 查找与正则表达式匹配的内容 在里面的某个地方 输入字符串。最后, Matcher.lookingAt 将正则表达式与 开始 输入字符串。

    如果您正在使用 比赛 您可能需要 .* 在末尾匹配整个字符串。但是,您最好使用其他方法中的一种,这样您就可以省去 * . 听起来像 看火柴的人 可能适合您的目的。

        2
  •  2
  •   Michael    15 年前

    为什么不直接拿出来 * 你不需要它。

    ^\\s+?(\\w+?)
    
        3
  •  1
  •   Alan Moore Chris Ballance    15 年前
    .*?id="number"[^>]*?>([^<]+?).*
    

    那真的是你用的瑞格鞋吗?我问的原因是 ([^<]+?) 总是只匹配一个字符,就像你写的一样 ([^<]) 相反。这个 + 量词必须至少匹配一次,但因为它不愿意,所以它会立即传递给下一部分。- .* -总是成功的。去掉 * 然后切换到 find() lookingAt() 也不会改变这种行为(尽管获得相同结果可能要快一点)。如果要将所有文本与下一个尖括号匹配,应去掉问号: ([^<]+) .

    [^>]*?> 也没什么意义。在匹配括号之前,必须使用尽可能多的非括号,那么让量词不愿意使用的意义是什么呢?事实上,也没有必要让它贪婪;如果 [^>]* 尽可能匹配,下一个字符不是“>”,您知道回溯不会有任何好处。你也可以用所有格量词- [^>]*+> -或原子团- (?>[^>]*+)> -如果你的regex口味支持的话。

    第一个量化部分- .*? -是唯一正确使用的(如果不是最佳的)。把它放在正则表达式的开头可以模拟 查找() 当你使用 查找() 或(用) * 最后) matches() . 但是,将其关闭并使用 查找() 如你所发现的,效率更高。

    不情愿的量词是非常方便的,但最近似乎他们已经过度曝光。随着频率的增加,我看到人们给出的建议“使用不情愿的量词”,没有任何解释或限定——只是另一个银弹。我相信像这个问题中的正则表达式就是结果。在这三个不情愿的量词中,一个应该贪婪,一个应该占有,另一个根本不应该存在。

    编辑:这里有一个例子来说明我所说的一些内容,并介绍斯蒂芬C的评论。给定此字符串:

    <div id="number" class="whatever">abc123</div>
    

    …regex的动态部分如下所示:

    .*?         => '<div '
    
    [^>]*?      => ' class="whatever"'
    
    ([^<]+?)    => 'a'
    
    .*          => 'bc123</div>'
    

    将所有不情愿的量词都改为贪婪的量词并不会改变整体匹配(整个字符串),也不会改变前两个动态部分匹配的内容。但最后两个被重新任命:

    ([^<]+)     => 'abc123'
    
    .*          => '</div>'
    

    看看原来的regex,我想这一定是我们想要的结果;如果不捕获整个内容,为什么要在捕获组中使用如此复杂的子表达式呢? 'abc123' ?正因为如此,我才相信那些不情愿的量词被盲目地用作一种灵丹妙药。

    还有一件事:回过头来,我发现手术实际上没有 他把 *? 当他切换到 查找() 方法。@本,如果你没有这样做的话,你应该这样做;这只是在减缓事情的发展。这会给你留下这个regex:

    id="number"[^>]*+>([^<]+)
    

    我也不想让任何人认为我在质疑被接受的答案。我只是在挠我的痒,因为不情愿量词的过度使用/不当使用。

        4
  •  0
  •   Thorbjørn Ravn Andersen    15 年前

    如果您处理的是HTML,除非您对数据文件有100%的控制权,否则正则表达式不是进行分析的正确工具。它最终会破裂。

    在我看来,你需要的标签内容有id=“number”,显然更多。存在宽泛的解析器,允许在HTML输入上进行XSLT转换,这可能正是您所需要的。如果你感兴趣的话,我会查的。

        5
  •  0
  •   user122299    15 年前

    有一个很好的库可以处理HTML文件——包括格式不好的真实文件:漂亮的汤 http://www.crummy.com/software/BeautifulSoup/

    用这个库很容易找到你的id=tag

        6
  •  0
  •   Stephen C    15 年前

    在这种特殊情况下,简单的答案是使用“find”而不是“matches”。但是,如果这对你不起作用,Java模式类支持用可以防止回溯的所谓所有格量词的正则表达式。

    占有量词是贪婪量词和不情愿量词的第三种选择。Java中的语法是“x”?+'或'X*+'或'X++'。所有格量词匹配尽可能多的字符(如贪婪量词),但如果模式的其余部分不匹配,所有格量词将失败而不是后退。(有点像序言中的“切口”)。

    但是要注意,使用所有格量词而不是贪婪或不情愿的量词会改变你模式的含义。

    有关所有格量词的教程信息位于 this page .