假设您的正则表达式引擎支持lookbehinds、原子组和所有格量词(即 PCRE 功能):
可以替换的一些示例:
*(即:|(?:(?<!sh|ch|zh)(?<=h)uang|(?<!sh|ch|...|(?<!sh|ch|zh)(?<=h)u)
)
*(即:|(?:(?<!r|c|b|d|g|f|h|k|j|m|l|n|q|p|s|t|w|y|x|z)a|(?<!r|c|b|d|...))$
)
其他部分如何处理:
example:
(?:(?<=ch)uang|(?<=ch)ang|(?<=ch)eng|(?<=ch)ong|(?<=ch)uai|(?<=ch)uan|(?<=ch)ai|(?<=ch)an|(?<=ch)ao|(?<=ch)en|(?<=ch)ou|(?<=ch)ua|(?<=ch)ui|(?<=ch)un|(?<=ch)uo|(?<=ch)a|(?<=ch)e|(?<=ch)i|(?<=ch)u)
_ 所有此类部件都具有相同的lookbehind,您必须为每个部件执行以下步骤 _
# step 1: lookarounds factorization
(?<=ch)(?>ang|eng|ong|uai|uan|ai|an|ao|en|ou|ua|ui|un|uo|a|e|i|u)
# step 2: sort all the content by alphabetic order
(?<=ch)(?>a|ai|an|ang|ao|e|en|eng|i|ong|ou|u|ua|uai|uan|ui|un|uo)
# step 3: group by first letter: don't forget the ? if the letter can be alone
(?<=ch)(?>a(?>i|n|ng|o)?|e(?>n|ng)?|i|o(?>ng|u)|u(?>a|ai|an|i|n|o)?)
# step 4: reduce the terminations (ie: n & ng => ng?+)
(?<=ch)(?>a(?>i|ng?+|o)?|e(?>ng?+)?|i|o(?>ng|u)|u(?>a[in]?+|i|n|o)?)
# step 5: put single letters in a character class
(?<=ch)(?>a(?>[io]|ng?+)?|e(?>ng?+)?|i|o(?>ng|u)|u(?>a[in]?+|[ino])?)
结论
虽然结果较短,但这里的目标是优化。我减少了因式分解的测试数量以及使用原子组和所有格量词的回溯数量。
一些限制
请注意,正则表达式具有如下功能原子团 http://www.regular-expressions.info/atomic.html and 所有格量词 http://www.regular-expressions.info/possessive.html并非所有正则表达式风格都支持,但可以解决该问题:
- 对于不支持所有格量词的风格:更改
?+
to ?
- 对于不支持原子组的口味:更改
(?>
to (?:
(请注意,使用 Python 建立原子组有一个技巧,您可以使用计时器进行测试,以包围所有模式。请参阅这篇令人难以置信的文章:Python 正则表达式是否具有与 Ruby 原子分组等效的功能? https://stackoverflow.com/questions/13577372/do-python-regular-expressions-have-an-equivalent-to-rubys-atomic-grouping)
某些正则表达式引擎(例如 javascript)不支持lookbehinds。在这种情况下,您必须仅使用交替来重写所有模式(即|
),这并不是一件坏事,因为后视会让你的模式变慢;并放弃也不支持的命名捕获。 (在这种情况下,应该注意的是,要删除否定的lookbehinds,您需要将这些部分中描述的音节放在所有其他部分之前,以便它们首先匹配。)
其他优化方式
- 重写你的模式而不使用lookbehinds并使用
|
instead
- 按最常用的音节对不同的行进行排序