【问题标题】:Matching greedy vs non-greedy operations in Tcl在 Tcl 中匹配贪婪与非贪婪操作
【发布时间】:2014-09-15 12:30:19
【问题描述】:

假设我想匹配一个文本下面的文本,

[ OK - 977613837 bytes ] 

我可以通过多种方式编写正则表达式。考虑以下代码,

set length "\[ OK - 977613837 bytes \]"
puts $length

#can be many ways, I am just keeping 2, to have it for question's sake
puts [ regexp -inline {\[\s+OK\s+-\s+\d+\s+bytes\s+\]} $length ] 
puts [ regexp -inline {\[.*OK.*\d+.*bytes.*\]} $length ]

这两个正则表达式都可以让我知道匹配的文本是否可用。

假设我不关心子匹配文本并假设文本将是一致的(即在最后一个右方括号之后不会有任何内容。)。我之所以说文本将是一致的,是为了避免贪婪的运算符获得更多的文本。

我相信在这种情况下,在这个给定的条件下,两者可以具有相同的含义。

问起来可能有点傻,但就执行时间而言,哪个正则表达式更有效?

【问题讨论】:

  • 我推荐这个puts [ regexp -inline {\[\s+OK\s+\-\s+\d+\s+bytes\s+\]} $length ] ,因为使用这个正则表达式可以避免回溯。
  • 好问题。测试了一下,发现了一些令我惊讶的结果。到目前为止,最快的是使用{\[\s*OK\s*-\s*\d+\s*bytes\s*\]}
  • 嗯,实际上,{\[\s*OK\D*\d+\s*bytes\s*\]} 是当前最快的.
  • @Jerry:只有最后一个会匹配很多不是空格单破折号空格的字符串。
  • @Dinesh,实际上我在对您问题的第二条评论中隐藏了一个链接。尝试将鼠标悬停在“最快”之后的点上,您将获得一个链接,我在其中计时了 5 个不同的正则表达式。你也许可以选择你喜欢的:)

标签: regex tcl


【解决方案1】:

很难预测最快的 RE 将是多少,尤其是在输入非常有限的情况下。正则表达式可以在开始时快速匹配但通常慢,或者快速匹配但慢匹配失败,等等。您还必须注意,捕获任何内容都会减慢引擎速度,any 回溯也是如此。使用time 命令进行调查。

% set length "\[ OK - 977613837 bytes \]"
[ OK - 977613837 bytes ]
% puts [regexp -inline {\[\s+OK\s+-\s+\d+\s+bytes\s+\]} $length]
{[ OK - 977613837 bytes ]}
% time {regexp -inline {\[\s+OK\s+-\s+\d+\s+bytes\s+\]} $length}
26 microseconds per iteration
% time {regexp -inline {\[\s+OK\s+-\s+\d+\s+bytes\s+\]} $length} 1000
8.996317 microseconds per iteration
% time {regexp -inline {\[\s+OK\s+-\s+\d+\s+bytes\s+\]} $length} 10000
6.5541893 microseconds per iteration
% time {regexp -inline {\[\s+OK\s+-\s+\d+\s+bytes\s+\]} $length} 100000
6.42272296 microseconds per iteration

(请注意,增加迭代次数会使每次迭代的时间更准确。)

尽管有一些一般要点:Tcl 缓存已编译的 RE,以便连续几次运行相同的 RE 很快。它有多种管理缓存的方法,但是缓存非常可以很好地与 RE 一起使用,无论是文字还是存储在全局/命名空间变量中(前提是您不修改变量)。

并且确保您在运行计时之前使用的是优化的 Tcl 构建。调试构建要慢得多。

【讨论】:

  • 感谢多纳尔的解释
猜你喜欢
  • 2017-10-16
  • 1970-01-01
  • 2015-02-11
  • 2017-05-07
  • 2011-08-29
  • 2012-11-17
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
相关资源
最近更新 更多