【问题标题】:use case for ?: in tcl regexp? 的用例:在 tcl 正则表达式中
【发布时间】:2016-07-18 14:07:24
【问题描述】:

我在 tcl regexp 中阅读了?: 的文档。这表示它匹配一个表达式而不捕获它。

我试过了,效果很好。 我的问题是,这个选项的正确用例是什么,因为我们不想使用捕获序列,所以我们不会在那里放置括号。

它只是一种替代方式,还是有一些特殊条件,我们应该在哪里使用它?请澄清。

【问题讨论】:

标签: regex tcl


【解决方案1】:

简单:您需要在 Regex 中对多个元素进行分组,但您不需要将它们作为捕获组以供参考。

a+ (b+|c+) OR (a+ b+)|c+

我需要大括号进行分组。但是,如果我这样运行它,引擎将捕获所有这些匹配项。这可能需要大量内存并消耗大量性能。如果我以后不需要捕获组以供参考,我可以使用 ?: 在不影响性能的情况下进行分组:

a+ (?:b+|c+) OR (?:a+ b+)|c+

【讨论】:

  • 这可能需要大量的内存并消耗大量的性能。 这实际上并不是一个消耗资源的操作。关键是该组的堆栈没有创建和填充,但它并不总是要求操作。要点是非捕获组用于分组 - 没有其他用途,因此,不会破坏模式中已经定义的捕获组的现有顺序,或者您将在稍后定义。
  • 我在其他问题中运行了一些基准测试,其中单个组更改为非捕获将运行时间减少了 30% 我认为可以构建更多示例
  • 但是很多这些点都在重复问题的好答案中讨论过,我想这个很快就会关闭
  • 我不会关闭这个,但是,我希望为 Tcl 量身定制更详细的答案。非捕获组真的很有帮助。
  • @Mariano 为下一个程序员编写明确的代码有何意义?我尝试将我的正则表达式写得尽可能清晰易读。
【解决方案2】:

首先,看一下 Tcl 正则表达式参考:

(expression)
表达式周围的括号指定嵌套表达式。 子串匹配表达式捕获可以通过反向引用机制被引用,也可以被捕获到任何对应的匹配变量指定为命令的参数(?:expression)
匹配表达式而不捕获它。

虽然第一部分描述捕获组捕获要通过反向引用引用的子文本的能力是通用的,但第二部分详述基于捕获组初始化变量是特定于 Tcl 的。

请记住,使用非捕获组可以大大简化 Tcl 正则表达式的使用如果您有一个包含多个捕获组的模式,并且您想通过在现有之间添加另一个组来修改它组

说,你想匹配abc 1234 (comment)之类的字符串并使用{(\w+)\s+(\d+)\s+\(([^()]+)\)}

regexp {(\w+)\s+(\d+)\s+\(([^()]+)\)} $a - body num comment

但是,您还被要求在 1234comment 之间匹配任意数量的 word+space+digits 字符串。如果你写

set a1 "abc 1234 more 5678 text 890 here 678 (comment)"
regexp {(\w+)\s+(\d+)(\s+\w+\s+\d+)*\s+\(([^()]+)\)} $a - body1 num1 comment1
                     ^^^^^^^^^^^^^^^

$comment 将保存一个您意想不到的值。

把它变成一个-捕获组可以解决这个问题。

IDEONE demo

非捕获组的其他常见用法,请参考Are optional non-capturing groups redundant 帖子。

【讨论】:

  • 您需要更多说明吗?如果你这样做,请不要犹豫,发表评论。
【解决方案3】:

当匹配多个您不想捕获的单词选项时,您可以在正则表达式中使用() 括号。

(?:one|two|three)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多