为什么更换\s*(或甚至\s\s*)\s+导致此输入的加速?
use Benchmark qw(:all);
$x=(" " x 100000) . "_\n";
$count = 100;
timethese($count, {
'/\s\s*\n/' => sub { $x =~ /\s\s*\n/ },
'/\s+\n/' => sub { $x =~ /\s+\n/ },
});
Run Code Online (Sandbox Code Playgroud)
我注意到s/\s*\n\s*/\n/g我的代码中有一个缓慢的正则表达式- 当给出一个450KB的输入文件,其中包含大量空格,其中有一些非空格,最后一个换行符 - 正则表达式挂起并且从未完成.
我直观地取代了正则表达式,s/\s+\n/\n/g; s/\n\s+/\n/g;一切都很顺利.
但为什么它这么快?使用后re Debug => "EXECUTE"我注意到\s+版本以某种方式优化,只在一次迭代中运行:http://pastebin.com/0Ug6xPiQ
Matching REx "\s*\n" against " _%n"
Matching stclass ANYOF{i}[\x09\x0a\x0c\x0d ][{non-utf8-latin1-all}{unicode_all}] against " _%n" (9 bytes)
0 <> < _%n> | …Run Code Online (Sandbox Code Playgroud) 我需要捕获相同模式的多个组.假设,我有一个以下字符串:
HELLO,THERE,WORLD
Run Code Online (Sandbox Code Playgroud)
我写了一个以下模式
^(?:([A-Z]+),?)+$
Run Code Online (Sandbox Code Playgroud)
我想要它做的是,捕获每一个单词,以便第1组是:"你好",第2组是"THERE"而第3组是"WORLD"我的正则表达式实际上只捕获最后一个,这是"世界".
我测试我的正则表达式在这里,我想与斯威夫特使用它(也许有斯威夫特一种方式来获得中间结果不知怎么的,这样我就可以使用它们?)
更新:我不想使用split.我现在只需要捕获所有匹配模式的组,而不仅仅是最后一组.
我正在测试一个Regex模式匹配信用卡的应用程序,然后突出显示这些数字.我正在使用网站http://regexpal.com/为我的测试创建测试信用卡信用卡号码.我的要求是拥有有效的信用卡号码,它们之间可以有" - "和/或",".我没有成功建立这样的数字,就像我使用网站测试它一样
下面的方案我需要很少的信用卡号码
对于初学者编写正则表达式来说,这似乎是一个巨大的混乱源,可能会导致隐藏的性能问题,并且看起来典型的用例将是非贪婪的.
这只是出于遗留原因(它是如何首次完成的,每个实现都复制了),还是有原因的?
IMO,这个查询应该返回 A=1,B=2,
SELECT regexp_substr('A=1,B=2,C=3,', '.*B=.*?,') as A_and_B FROM dual
Run Code Online (Sandbox Code Playgroud)
但它返回整个字符串A=1,B=2,C=3,.为什么?
UPD: Oracle 10.2+需要在正则表达式中使用Perl样式的元字符.
UPD2:
我的问题的更清晰形式(以避免有关Oracle版本和Perl样式正则表达式扩展的可用性的问题):
为什么在相同系统上非贪婪量词有时按预期工作,有时不工作?
这工作正常:
regexp_substr('A=1,B=2,C=3,', 'B=.*?,')
Run Code Online (Sandbox Code Playgroud)
这不起作用:
regexp_substr('A=1,B=2,C=3,', '.*B=.*?,')
Run Code Online (Sandbox Code Playgroud)
UPD3:
是的,这似乎是一个错误.
任何人都可以就此问题提供Oracle支持响应吗?
这个虫子已经知道了吗?
它有ID吗?
有这个问题让我意识到量词的贪婪在某些正则表达式引擎中并不总是相同的.从该问题中取出正则表达式并对其进行修改:
!\[(.*?)*\]
Run Code Online (Sandbox Code Playgroud)
(我知道*这里多余,但我发现接下来的事情是一个非常有趣的行为).
如果我们尝试匹配:
![][][]
Run Code Online (Sandbox Code Playgroud)
我希望第一个捕获组变为空,因为它(.*?)是懒惰的并且会在]它遇到的第一个停止时停止.这确实发生在以下情况:
][][.(jsfiddle)我环顾了一些其他语言,例如ruby,java,C#,但所有行为都像我期望的那样(即返回空捕获组).
(regexplanet的golang风味显然也得到非空捕获组)
似乎JavaScript的正则表达式引擎正在解释第二个从懒惰*转换.*?为贪婪的引擎.需要注意的是转换的第二*到*?似乎让如我所料的正则表达式的工作(一样完全去除量词,因为我知道它是多余的在这种情况下,但是这不是重点).
*在正则表达式中使用,但这种行为类似于+,?或者{m,n}将它们转换为它们的懒惰版本给出了与之相同的结果*?.
有谁知道真正发生了什么?
如何在以下示例中获取所有匹配项:
// Only "abcd" is matched
MatchCollection greedyMatches = Regex.Matches("abcd", @"ab.*");
// Only "ab" is matched
MatchCollection lazyMatches = Regex.Matches("abcd", @"ab.*?");
// How can I get all matches: "ab", "abc", "abcd"
Run Code Online (Sandbox Code Playgroud)
PS:我希望以通用方式获得所有比赛.上面的例子只是一个例子.
对于在分隔符(例如<和>)之间匹配文本的常见问题,有两种常见的模式:
*或+量词START [^END]* END,例如<[^>]*>,或*?或+?量词START .*? END,例如<.*?>.是否有一个特别的理由支持一个而不是另一个?
我总是写这样的正则表达式
<A HREF="([^"]*)" TARGET="_blank">([^<]*)</A>
Run Code Online (Sandbox Code Playgroud)
但我刚刚了解了这个懒惰的东西,我可以这样写
<A HREF="(.*?)" TARGET="_blank">(.*?)</A>
Run Code Online (Sandbox Code Playgroud)
使用第二种方法有什么不利之处吗?正则表达式肯定更紧凑(即使SO更好地解析它).
编辑:这里有两个最佳答案,指出表达式之间的两个重要差异.ysth的答案指向非贪婪/懒惰的弱点,其中超链接本身可能包含A标签的其他属性(绝对不好).Rob Kennedy在贪婪的例子中指出了一个弱点,因为锚文本不能包含其他标签(绝对不行,因为它也不会抓住所有的锚文本)......所以答案是,正则表达式就是他们的是,懒惰和非懒惰的解决方案似乎相同可能在语义上不等同.
编辑:第三个最佳答案是Alan M关于表达式的相对速度.暂时,我会将他标记为最佳答案,以便人们给他更多积分:)
regex ×10
regex-greedy ×10
greedy ×2
non-greedy ×2
c# ×1
javascript ×1
oracle ×1
oracle10g ×1
oracle11g ×1
perl ×1
regex-group ×1
swift ×1