我有一个为文本的每一行调用的函数。
def tokenize_line(line: str, cmd = ''):
matches = re.finditer(Patterns.SUPPORTED_TOKENS, line)
tokens_found, not_found, start_idx = [], [], 0
print(matches)
for match in matches:
pass
# Rest of code
print(matches)
的结果类似于:
<callable_iterator object at 0x0000021201445000>
但是,当我将迭代器转换为列表时:
matches = list(re.finditer(Patterns.SUPPORTED_TOKENS, line))
或者当我用 | 进行迭代时||:
for
...Python 冻结。
for match in matches:
print(match)
此问题的发生不一致。例如:
因此,当将 callable_iterator 转换为列表或对其进行迭代时,就会出现问题。
tokenize_line('$color AS $length') # Works fine
tokenize_line('FALSE + $length IS GT 7 + $length IS 4') # Freezes
这是我正在使用的模式 (Patterns.SUPPORTED_TOKENS):
正则表达式模式的说明:
(°p\d+°|°a\d+°|°m\d+°)|((?<!\S)(?:!\'(?:\\.|[^\'\n\\])*\'|!"(?:\\.|[^\n"\\])*")(?!\S))|((?:\'(?:\\.|[^\'\n\\])*\'|"(?:\\.|[^\n"\\])*"))|((\{(.*)\}))|((?<!\S)([@$][\w]*(?:\.[\w]*)*)(?!\S))|((?<!\d)-?\d*\.?\d+)|(\*\*|[\+\-\*\(\)/%\^]|==|&&|\|\||!=|>=|<=|>|<|~~|!~~|::|!::)|([\:/])|(\b(?:AS|AND|AT|:|BETWEEN|BY|FROM|IN|INTO|ON|OF|OR|THAN|TO|USING|WITH)\b)|(\b[a-zA-Z_][a-zA-Z0-9_]* *((?:[^;()\'""]*|"(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|\([^)]*\))*?;))|((\b(?:EMPTY|STRING|NUMBER|BOOL|ARRAY|MAP|TRUE|FALSE|NULL|UNKNOWN|DOTALL|IGNORECASE|MULTILINE|ARRAY_ARRAY|ARRAY_STRING|ARRAY_MAP|ARRAY_NUMBER|ARRAY_NULL|DOT|SPACE|NEWLINE|SEMICOLON|COLON|HASH|COMMA|TAB)\b)|(\b(?:IS NOT LT|IS NOT GT|IS NOT GEQ|IS NOT LEQ|IS NOT|IS LT|IS GT|IS GEQ|IS LEQ|IS|NOT IN|NOT|IN|HAS NOT|HAS|AND|OR)\b))
自定义标记:
匹配以特定字符开头并后跟数字的特定自定义标记。 带引号的字符串:
匹配单引号和双引号字符串,包括带有转义字符的字符串。 大括号内容:匹配大括号内的任何内容。 变量:
匹配以特定字符(如 @ 或 $)开头的变量,并且可以包含嵌套属性的点。 数字:
同时匹配整数和浮点数,包括负数。 运算符:
匹配各种数学和逻辑运算符。 冒号和斜杠:匹配特定的标点符号,例如冒号和斜杠。 关键字:
匹配语言中保留的某些关键字。 函数定义:匹配函数定义或类似结构,确保它们遵循特定的语法规则。 数据类型和修饰符:
匹配表示数据类型或修饰符的关键字。 逻辑运算符:
匹配复杂逻辑运算符在条件表达式中使用。 任何帮助理解为什么会发生这种情况以及如何修复它的帮助将不胜感激!
Any help to understand why this happens and how to fix it would be greatly appreciated!
Python 冻结的问题,特别是当它与特定输入字符串有关但没有引发错误时,通常表示正则表达式中存在导致灾难性回溯的问题。灾难性回溯发生在正则表达式引擎在尝试所有可能的匹配组合时陷入困境时,从而导致指数级长的执行时间。
的正则表达式很长且很复杂,因此很难确定导致问题的具体原因。但是,有一些部分特别容易受到灾难性回溯的影响:
-
嵌套量词和交替运算符: 像
((?:[^;()'""]*|"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*'|([^)]*)*))*
这样的模式在与输入字符串不匹配时,可能会导致大量的回溯。因为有很多种方法可以使用不同的交替组合来匹配或不匹配子字符串,所以引擎必须尝试所有组合,从而导致指数级复杂度。 -
过于宽泛的匹配: 像
.*
和[^;()'""]*
这样的模式可以匹配非常多的字符,这也可能导致大量的回溯。例如,如果.*
的意图是仅匹配单行内的任何内容,则应将其替换为[^;\n]*
。
如何调试和修复此问题:
- 简化正则表达式: 尝试将的正则表达式分解为更小、更具体的模式。这将使更容易识别导致问题的部分。
-
使用非捕获组:
除非需要捕获子模式,否则请对不参与最终结果的组使用非捕获组
(?:...)
。这可以提高性能并减少回溯。 -
使量词更具体:
避免使用过于宽泛的量词,例如
*
和+
,尤其是在嵌套模式中。尝试使用更具体的量词,例如{1,3}
或{0,1}
,或使用字符类来限制匹配的字符,例如[a-z0-9]
。 - 使用正则表达式调试器: 有许多在线工具可以帮助可视化正则表达式的工作方式并识别潜在问题。例如, https://regex101.com/ 或 https://debuggex.com/ 。
- 考虑使用其他解析方法: 如果的正则表达式过于复杂,可能需要考虑使用其他解析方法,例如编写自定义解析器。
对于的具体情况,可以尝试以下操作:
- 分析导致冻结的输入字符串: 确定导致问题的特定输入字符串,并尝试隔离导致冻结的正则表达式部分。
- 逐步简化正则表达式: 从一个简化的正则表达式版本开始,然后逐渐添加复杂性,每次添加后测试性能。这将帮助确定导致问题的具体部分。
- 使用正则表达式调试器: 使用正则表达式调试器可视化引擎如何处理的模式和输入字符串。这可以帮助识别回溯发生的位置以及原因。
总而言之,解决正则表达式中的灾难性回溯问题可能很棘手,但这通常是通过仔细分析模式、简化模式和使用适当的工具来实现的。
标签:python,python-3.x,regex,loops,freeze From: 78776597