【问题标题】:Alternatives to Regular Expressions正则表达式的替代品
【发布时间】:2010-10-05 14:03:24
【问题描述】:

我有一组字符串,其中嵌入了数字。它们看起来像 /cal/long/3/4/145:999 或 /pa/metrics/CosmicRay/24:4:bgp:EnergyKurtosis。我想要一个表达式解析器是

  • 易于使用。举几个例子,某人应该能够形成一个新的表达方式。我希望最终用户能够形成新的表达式来查询这组字符串。有些潜在用户是软件工程师,有些是测试人员,有些是科学家。
  • 允许对数字进行限制。类似 '/cal/long/3/4/143:#>100&
  • 支持“|”和。所以表达式 '/cal/(long|short)/3/4/' 将匹配 '/cal/long/3/4/1:2' 以及 '/cal/short/3/4 /1:2'。
  • 有可用的 Java 实现或很容易用 Java 实现。

有趣的替代想法会很有用。我也在考虑只实现我需要的正则表达式子集以及数字约束的想法。

谢谢!

【问题讨论】:

  • 这就是正则表达式的设计目的。
  • 我不太明白您为什么要替代正则表达式。如果你能解释一下,也许它会帮助我们给出一个好的答案。我的建议是使用符合您需求的正则表达式子集。
  • 啊;我知道了。您列表中的 #2 超出了大多数普通正则表达式引擎的范围。 :)
  • 没错,对数字的限制使得使用普通的正则表达式变得困难。否则我只会使用它们,不会问这个问题。 :)

标签: java regex parsing


【解决方案1】:

没有理由重新发明轮子!正则表达式引擎的核心是建立在数学和计算机科学的坚实基础之上;我们今天继续使用它们的原因是它们基本上是健全的,并且在可预见的将来不会得到改进。

如果您确实找到或创建了一些仅涵盖 Regex 可能的子集的替代解析语言,您很快就会有用户要求可以用 Regex 表达的概念,但您的风格只是简单地忽略了。把时间花在解决尚未解决的问题上!

【讨论】:

  • 正则表达式在数学上是合理且快速的。但就易用性和可维护性而言,它们很糟糕。在这方面,他们是纯粹的邪恶。这就是为什么要重新发明的原因。
  • @BT 可以用任何人不熟悉的语言说。
  • 我不同意。正则表达式至少过于简洁且难以阅读。我相信这是一种意见,但我已经学会了它们,忘记了它们,重新学习了它们。
  • 看看 lex / yacc 如何使用由命名组件构建的正则表达式。与在一个可怕的 perl 风格的正则表达式中编写所有内容相比,这是一种更好的方法。
  • @RexM:你有 5 秒的时间阅读一行正则表达式并告诉我它的作用。你准备好了吗?去:(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)。阅读正则表达式就像阅读汇编:是的,这是可能的,但不,你不应该这样做。令我惊讶的是,还没有基于 Regex 构建的更高、更易读的语言。
【解决方案2】:

其实你描述的是JavaPatternMatcher。恰好使用正则表达式作为其语言。

【讨论】:

  • 据我所知,没有办法扩展或更改 Pattern 使用的语法。
  • 我不明白您为什么要这样做,但是您应该能够将 vars 拉入模式中,这样可以扩展它。 Java Pattern Matcher 是目前最有效的 RegEx 工具之一。 Java 中有太多不好的事情需要改变,无法与其中一位伟大的人混淆。
【解决方案3】:

不幸的是,并不是所有的程序员(包括我自己)都像他们应该熟悉的那样熟悉 RegEx。这通常意味着我们最终会编写自己的字符串解析逻辑,否则 RegEx 本来可以很好地为我们服务。

这并不总是坏事。在某些情况下,可以编写更优雅、更易读并满足您的问题域的精确需求的 DSL(一个类,一组内聚的方法)。问题在于,可能需要数十次迭代才能将问题提炼成简单直观的 DSL。只有当 DSL 将在应用程序或大型社区中广泛使用时,才会出现这种麻烦。不要为偶尔出现的问题编写优雅的解决方案。

【讨论】:

    【解决方案4】:

    我倾向于同意 Rex M,尽管您对数值约束的第二个要求使事情变得复杂。除非您只允许非常基本的约束,否则我不知道用正则表达式简洁地表达它的方法。如果有这样的方法,请忽略我的其余答案并按照此处的其他建议进行操作。 :)

    您可能需要考虑使用解析器生成器——例如经典的 lex 和 yacc。我对 Java 的选择不是很熟悉,但这里有一个列表:

    http://java-source.net/open-source/parser-generators

    如果您不熟悉,标准方法是首先创建一个lexer,将您的字符串转换为标记。然后,您会将这些标记传递给解析器,该解析器将您的语法应用于它们并吐出某种结果。

    在您的情况下,我设想解析器会产生正则表达式和附加条件的组合。对于您的数值约束示例,它可能会为您提供正则表达式 \/cal/long/3/4/143:(\d+)\ 和应用于第一个分组(\d+ 部分)的约束,该分组要求数字介于 100 和 1100 之间。然后您将应用 RE到您的候选人字符串,并将约束应用于这些候选人以找到您的匹配项。

    这是一个相当复杂的方法,所以希望有一个更简单的方法。我希望这至少能给你一些想法。

    【讨论】:

      【解决方案5】:

      Java 约束是一个严重的约束。我建议使用解析组合器,但您必须使用类而不是函数将这些想法转换为 Java。关于这个主题有很多很多的论文;最容易接近的方法之一是Graham Hutton's Higher-Order Functions for Parsing。正如您在示例中所展示的那样,Hutton 的方法使得根据诸如数字大小等条件来决定成功或失败变得特别容易。

      【讨论】:

        【解决方案6】:

        如果您打算使用解析器路线,请查看 GOLD 解析系统。它通常是比 YACC 更好的选择,比纯正则表达式更简洁,并且支持 Java。

        http://goldparser.org/about/how-it-works.htm

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多