我有这个正则表达式:
(?:.*[a-zA-Z0-9].*){3}
我用它来查看字符串中是否至少包含3个字母数字字符。它似乎有效。
它应匹配的字符串示例:
'a3c'
'_0_c_8_'
' 9 9d '
但是,我需要它更快地工作。有没有更好的方法来使用正则表达式匹配相同的模式?
编辑: 我最终将此regex用于我的目的:
(?:[^a-zA-Z0-9]*[a-zA-Z0-9]){3}
(不需要修饰符)
答案 0 :(得分:6)
最有效的正则表达式方法是使用principle of contrast,即并排使用相反的字符类。这是一个正则表达式,可用于检查字符串是否有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]*+
。
答案 1 :(得分:3)
(?:.*?[a-zA-Z0-9]){3}.*
你可以使用它。这比你的快得多,步骤也少。参见demo。你可能也想使用^$
锚来确保没有部分匹配。
https://regex101.com/r/nS2lT4/32
原因是
(?:.*[a-zA-Z0-9].*){3}
^^
这实际上消耗了整个字符串,然后引擎必须回溯。当使用其他正则表达式时,这是避免的
答案 2 :(得分:2)
考虑一下。正则表达式非常强大,因为它们具有表现力且非常灵活(具有前瞻,贪婪消耗和反向跟踪等功能)。几乎总是是一个成本,无论多么轻微。
如果你想要原始速度(并且你愿意放弃表现力),你可能会发现完全绕过正则表达式并且仅仅评估字符串会更快,例如以下伪代码:
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 != '\0'; str++)
if (isalnum (ch))
if (++count == 3)
return 1;
return 0;
}
现在,关于这个具体情况是否更快,这取决于许多因素,例如语言是否被解释或编译,正则表达式的效率如何等等。
这就是为什么优化的口号是“测量,不要猜测!”您应该评估目标环境中的可能性。