【问题标题】:TCL string match vs regexpsTCL 字符串匹配与正则表达式
【发布时间】:2011-09-14 05:03:58
【问题描述】:

我们是否应该避免使用正则表达式,因为它很慢。相反,我们应该使用字符串操作。是否有两种情况都可以使用但正则表达式更好?

【问题讨论】:

    标签: regex string tcl string-matching


    【解决方案1】:

    您应该使用适当的工具来完成这项工作。这意味着,你不应该避免使用正则表达式,你应该在必要时使用它。

    如果您只是搜索固定的字符序列,请使用字符串操作。

    如果您正在搜索模式,请使用正则表达式。

    示例

    搜索单词“Foo”。使用字符串操作它也会发现 “Foobar”,这样可以吗?不,那么也许搜索“Foo”,但随后 它不会找到“Foo”和“Foo”。

    使用正则表达式没问题,您可以匹配单词边界 /\mFoo\M/ 和 这个正则表达式不会很慢。

    我认为这种负面形象来自catastrophic backtracking等特殊问题。

    最近有一个示例 (catastrophic-backtracking-shouldnt-be-happening-on-this-regex) 出现这种行为是意外的。

    结论

    必须精心设计正则表达式,否则性能可能是灾难性的。但是,如果您使用错误的算法,您的正常代码也会发生同样的情况。

    对于一项小型工作,使用正则表达式几乎不会成为问题,如果您的任务较大并且必须经常重复,请做一个基准测试。

    根据我自己的经验,我正在分析非常大的文本文件(大约数百 MB)并使用正则表达式来查找我感兴趣的行,并且我不会因为正则表达式而遇到性能问题。

    Here an interesting read about code optimization

    【讨论】:

      【解决方案2】:

      正则表达式 (RE) 是一把奇妙的锤子。他们可以优雅地解决一些问题,还可以用蛮力解决更多问题,但不会很漂亮。如果你打得足够多,一些问题可以用 RE 解决,但有更好的解决方案可用(例如,非常适合 string map 的东西)

      string match - 或 globbing - 可以被认为是正则表达式的简化版本。 glob 模式通常比等效的正则表达式短(字符类是一个例外 - ER 支持它们,您需要将 glob 拼出来)。我不知道性能有何不同。由于逻辑更简单,我希望 string match 在等效模式上稍快一些,但 time 比预期的要可靠得多。

      对于 RE 更易于使用的特定情况,根据上下文提取子字符串与通过简单字符位置提取子字符串是一个很好的示例。或用于匹配多个备选方案之一。

      我的经验法则是使用最简单的方法。如果那是string match,那就太好了。如果该模式看起来过于复杂,请转到正则表达式并很高兴您有选择。

      【讨论】:

      • 事实上,Tcl regexp 引擎会检测到一些可以通过string match 完成的简单模式,因此对于一些简单模式,您不会看到太大差异。
      • 确切地说,非常简单的正则表达式在 Tcl 字节码编译器中被转换为 string match 调用。任何复杂的东西都会进入主 RE 引擎。
      【解决方案3】:

      我能给出的最好的建议,以及我自己使用的建议是,只有在更简单的解决方案不起作用时才使用正则表达式。

      如果您可以使用简单的字符串匹配或使用 glob 模式,请使用它们。只有当那些不能工作时,你才应该使用正则表达式。

      为了解决您的具体问题,我想说,不,没有时间可以使用任何一种,但正则表达式是更好的选择。也许有一个我没有想到的极端情况,但一般来说,更简单的解决方案总是更好。

      【讨论】:

        【解决方案4】:

        我不特别了解 Tcl,但通常可以说,如果您正在寻找精确的文本匹配(例如,查找所有以 #define 开头的行),那么字符串操作会更快。但是,如果您正在寻找 模式(例如,所有包含以 c 开头并以 t 结尾的单词的行),那么正则表达式是解决此问题的正确工具(\bc\w*t\b 会成为一个很好的正则表达式 - 如果您必须自己编写,请将其与您需要的程序逻辑进行比较。

        即使在这种情况下正则表达式速度较慢,执行速度方面的可能性也很高,但是当需要更改匹配逻辑时,它会很重要(哦,现在我们需要查找以c 开头并以t 结尾但至少包含两个as 且没有x 的单词--> \bc(?=\w*a\w*a)(?!\w*x)\w*t\b)。

        大多数正则表达式引擎不想去的地方是递归(匹配嵌套标签、嵌套括号等等)。这就是解析器进入图片的地方。

        【讨论】:

        • 真正的正则表达式(在正则语言的意义上)不能匹配嵌套的括号(它们不能被抽出)。但大多数现代 RE 引擎允许相当多的非常规行为(如反向引用),因此您可能能够匹配它们。但是,您可能仍然不应该这样做。
        • @evil otto:这就是我写“大多数正则表达式引擎”的原因。它们中的大多数确实支持反向引用甚至环视,但只有少数支持递归和嵌套标签(PCRE、Perl 6、.NET)。你是对的,你可能仍然不应该。
        • Tcl 的 RE 引擎不支持递归;这是严格的自动机理论。
        【解决方案5】:

        正则表达式匹配是一种字符串操作。虽然它没有一些更基本的操作那么快,但它的能力也大大增强。它也更难使用,特别是如果您还不知道 RE 的基本语法,但这不是避免它们的理由。但是,用一组基本字符串操作替换正则表达式只会导致程序变得非常长:有时,您只需要复杂的操作。

        Tcl 做了很多事情来提高 RE 操作的效率。值得注意的是,它检测到特别简单的 RE 并将它们转换为类似 glob 的匹配(如在string match 中),这些匹配更快但功能要弱得多,并且它会做很多事情来缓存 RE 的编译形式,以便匹配的开销更少.它还使用了自动机理论匹配引擎,该引擎在匹配期间出现的意外更少(首先要花费更多时间来编译 RE)​​。

        简而言之,不要避开它们。在适当的地方使用它们。 (如果您对速度有疑问,还有time。)

        【讨论】:

          【解决方案6】:

          regexp 又名正则表达式用于匹配许多不同的字符串,可能非常复杂,甚至可以验证特定的输入。
          string match 仅允许使用通配符,例如 * 和 ? 以及基本字符与正则表达式中的[] 分组。
          你可以在这里阅读:http://www.tcl.tk/man/tcl8.5/TclCmd/string.htm#M40
          此处解释了正则表达式还可以通过一些示例执行的基本指南:http://www.regular-expressions.info/

          简而言之:如果您不需要正则表达式,或者甚至不太了解它,我建议您不要使用它。如果您只想比较两个字符串是否相等,请使用string equal。

          【讨论】:

          • 阅读 Mastering Regular Expressions ed 2 给我的印象是,由于正则表达式引擎的实现,灾难性回溯在 Tcl 中不是问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-24
          • 1970-01-01
          • 2022-01-17
          • 1970-01-01
          • 2019-05-01
          相关资源
          最近更新 更多