我有这个正则表达式:
(?:.*[a-zA-Z0-9].*){3}
我用它来查看一个字符串中是否至少有3个字母数字字符。它似乎有效。
它应该匹配的字符串示例:
'a3c'
'_0_c_8_'
' 9 9d '
然而,我需要它工作得更快。有没有更好的方法可以使用regex来匹配相同的模式?
编辑:我最终使用了这个正则表达式:
(?:[^a-zA-Z0-9]*[a-zA-Z0-9]){3}
(不需要修改器(
最有效的regex方法是使用对比度原则,即并排使用相反的字符类。这里有一个正则表达式,可以用来检查字符串是否有3个拉丁字母或数字:
^(?:[^a-zA-Z0-9]*[a-zA-Z0-9]){3}
请参阅演示。
如果你需要一个完整的字符串匹配,你需要附加.*
(或者.*$
,如果你想保证你会匹配到字符串/行的末尾(,但在我对regexhero的测试中,.*
产生了更好的性能(:
^(?:[^a-zA-Z0-9]*[a-zA-Z0-9]){3}.*
此外,这在很大程度上取决于发动机。PCRE具有包含自动占有的自动优化(即,它在(?:[^a-zA-Z0-9]*+
中将*
变成*+
(。
请在此处查看有关密码验证优化的更多详细信息。
(?:.*?[a-zA-Z0-9]){3}.*
你可以用这个。这比你的要快得多,所需的步骤也要少得多。请参阅演示。您可能也想使用^$
锚点来确保没有部分匹配。
https://regex101.com/r/nS2lT4/32
原因是
(?:.*[a-zA-Z0-9].*){3}
^^
这实际上消耗了整个字符串,然后引擎不得不回溯。当使用其他正则表达式时,可以避免
考虑一下。正则表达式之所以强大,是因为它们表现力强且非常灵活(具有前瞻性、贪婪消耗和回溯等功能(。几乎总会有的成本,无论多么小。
如果你想要raw的速度(并且你愿意放弃表达能力(,你可能会发现完全绕过正则表达式,只计算字符串会更快,比如使用以下伪代码:
def hasThreeAlphaNums(str):
alphanums = 0
for pos = 0 to len(str) - 1:
if str[pos] in set "[a-zA-Z0-9]":
alphanums++
if alphanums == 3:
return true
return false
它是一个解析器(在本例中是一个非常简单的解析器(,一个比正则表达式更强大的工具。要获得更具体的示例,请考虑以下C代码:
#include <ctype.h>
int hasThreeAlphaNums (char *str) {
int count = 0;
for (int ch = *str; ch != ' '; str++)
if (isalnum (ch))
if (++count == 3)
return 1;
return 0;
}
现在,对于这种特定的情况,这是否更快,取决于许多因素,例如语言是否被解释或编译,正则表达式的效率如何,等等
这就是为什么优化的口头禅是"测量,不要猜测!">您应该评估目标环境中的可能性。