正则表达式效率

Regex efficency

给出这个字符串

xxv jkxxxxxxxxxxxxxxx xxyu xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxAp oSxx
xxAp oSxxxxxxxxxxxxxxxxxxxxxj xxxxxxxxxuixxxxxxxxxxx axxxxxxxxxxxxxxxxxx

和这个正则表达式

^[^\r\n]*Ap oS[^\r\n]*

我希望在任何地方匹配包含 Ap oS 的任何行,如图 here 所示,它确实做到了。

现在,通过查看 debugger 可以看出,如果我理解正确的话,由于回溯,第一场比赛进行了 16 步,第二场比赛进行了 80 步。

我的问题是,如何编写这个正则表达式来减少步骤?

我想用(?!Ap oS)*替换第一个[^\r\n]*来匹配所有不是Ap oS的东西,直到它找到Ap oS,但我不确定我是否我的概念或语法有误,或两者都有。

感谢任何帮助

您想在此处应用 unroll-the-loop technique

^[^A\r\n]*(?:A(?!p oS)[^A\r\n]*)*Ap oS[^\r\n]*

regex demo

详情

  • ^ - 字符串开头
  • [^A\r\n]* - 除 CR、LF 和 A
  • 之外的 0+ 个字符
  • (?:A(?!p oS)[^A\r\n]*)* - 出现 0 次或多次 A 后跟 p oS,然后出现 0+ 个除 CR、LF 和 A[=36= 以外的字符]
  • Ap oS - 你的字符串
  • [^\r\n]* - 除 CR 和 LF 之外的 0 个或更多字符。

您可以使用以下模式之一以更简单有效的方式应用展开循环技术:

^(?:[^A\r\n]*A)+?p oS.*

demo

(请注意,pcre 使量词 *[^A\r\n]*A 中自动具有所有格,因为 A 跟随一个重复的字符 class 从那里排除.换句话说,用原子组替换这个子模式周围的非捕获组或者显式地使量词占有是没有用的。)

或者如果您希望文字部分完整显示:

^[^A\r\n]*+(?>A[^A\r\n]*)*?Ap oS.*

demo

您不需要使用前瞻,因为这是不情愿的量词在这里所做的(它在每次组迭代后测试下一个子模式)。


请注意,由于您正在查找包含文字字符串的行,并且如果您的数据来自文件,那么在许多编程语言中,逐行读取文件并使用基本字符串函数。


根据 pcre 中的默认换行序列和字符串中使用的换行序列,模式末尾的 .* 可以匹配回车 return。为避免这种行为,您可以明确设置什么是换行序列,以 (*CRLF).

开始您的模式

减少模式的步骤数是提高模式效率的一种方法,但请注意不要为此目的构建太长或太复杂的模式,因为它也可能适得其反。