正则表达式 PHP。减少步数:受限于固定宽度 Lookbehind
Regex PHP. Reduce steps: limited by fixed width Lookbehind
我有一个用于匹配@users 标签的正则表达式。
我使用 lokarround 断言,让标点符号和白色 space 字符包围标签。
还有一个复杂的问题,有一种 bbcodes 代表 html.
我有两种类型的 bbcode,内联(^B
粗体 ^b
)和块(^C
中心 ^c
)。
必须通过内联字符才能到达上一个或下一个字符。
并且允许块包围标签,就像标点符号一样。
我制作了一个有效的正则表达式。我现在想做的是减少它在每个不匹配的字符中执行的步骤数。
起初我以为我可以做一个只寻找 @
的正则表达式,当找到时,它会开始查看 lookarrounds,它在没有内联 bbcode 的情况下工作,但由于 lookbehind 无法量化,因此更加困难,因为我无法在里面添加 ((\^[BIUbiu])++)*
,产生更多的步骤。
我怎样才能用更少的步骤更有效地做我的正则表达式?
这是它的简化版本,在 Regex101 link 中有完整的正则表达式。
(?<=[,\.:=\^ ]|\^[CJLcjl])((\^[BIUbiu])++)*@([A-Za-z0-9\-_]{2,25})((\^[BIUbiu])++)*(?=[,\.:=\^ ]|\^[CJLcjl])
经验法则:
Do not let engine make an attempt on matching each single one character if
there are some boundaries.
引用原文来自这个回答。由于最外层交替的左侧,遵循正则表达式以显着的方式减少了步骤,从 ~20000 到 ~900:
(?:[^@^]++|[@^]{2,}+)(*SKIP)(*F)
|
(?<=([HUGE-CHARACTER-CLASS])|\^[cjleqrd])
(\^[34biu78])*+@([a-z\d][\w-.]{0,25}[a-z\d])(\^[34biu78])*+(?=(?1))
实际上,我不太关心 regex101 报告的步骤数,因为这在您自己的环境中是不正确的,并且某些步骤是否真实或遗漏了哪些步骤并不明显。但是在这种情况下,由于正则表达式的逻辑很清楚,而且差异很大,所以是有道理的。
这是什么逻辑?
我们首先尝试匹配可能根本不需要的东西,将其丢弃并寻找可能与我们的模式匹配的部分。 [^@^]++
匹配 @
或 ^
符号(所需字符),并且 [@^]{2,}+
防止引擎在发现它无处可去之前采取额外的步骤。所以我们让它尽快失败。
您可以使用 i
标志而不是定义字母的大写形式(但这可能会有一点影响)。
我有一个用于匹配@users 标签的正则表达式。
我使用 lokarround 断言,让标点符号和白色 space 字符包围标签。
还有一个复杂的问题,有一种 bbcodes 代表 html.
我有两种类型的 bbcode,内联(^B
粗体 ^b
)和块(^C
中心 ^c
)。
必须通过内联字符才能到达上一个或下一个字符。
并且允许块包围标签,就像标点符号一样。
我制作了一个有效的正则表达式。我现在想做的是减少它在每个不匹配的字符中执行的步骤数。
起初我以为我可以做一个只寻找 @
的正则表达式,当找到时,它会开始查看 lookarrounds,它在没有内联 bbcode 的情况下工作,但由于 lookbehind 无法量化,因此更加困难,因为我无法在里面添加 ((\^[BIUbiu])++)*
,产生更多的步骤。
我怎样才能用更少的步骤更有效地做我的正则表达式?
这是它的简化版本,在 Regex101 link 中有完整的正则表达式。
(?<=[,\.:=\^ ]|\^[CJLcjl])((\^[BIUbiu])++)*@([A-Za-z0-9\-_]{2,25})((\^[BIUbiu])++)*(?=[,\.:=\^ ]|\^[CJLcjl])
经验法则:
Do not let engine make an attempt on matching each single one character if there are some boundaries.
引用原文来自这个回答。由于最外层交替的左侧,遵循正则表达式以显着的方式减少了步骤,从 ~20000 到 ~900:
(?:[^@^]++|[@^]{2,}+)(*SKIP)(*F)
|
(?<=([HUGE-CHARACTER-CLASS])|\^[cjleqrd])
(\^[34biu78])*+@([a-z\d][\w-.]{0,25}[a-z\d])(\^[34biu78])*+(?=(?1))
实际上,我不太关心 regex101 报告的步骤数,因为这在您自己的环境中是不正确的,并且某些步骤是否真实或遗漏了哪些步骤并不明显。但是在这种情况下,由于正则表达式的逻辑很清楚,而且差异很大,所以是有道理的。
这是什么逻辑?
我们首先尝试匹配可能根本不需要的东西,将其丢弃并寻找可能与我们的模式匹配的部分。 [^@^]++
匹配 @
或 ^
符号(所需字符),并且 [@^]{2,}+
防止引擎在发现它无处可去之前采取额外的步骤。所以我们让它尽快失败。
您可以使用 i
标志而不是定义字母的大写形式(但这可能会有一点影响)。