OR 运算符内的 OR 运算符 - 正则表达式
OR operator inside OR operator - RegEX
我正在尝试在 python 中创建一个编译器,并且我正在使用 re
模块来创建标记。语言将与 Assembly
.
非常相似
几乎一切正常,但我在使用令牌时遇到问题。让我举例说明这个标记是什么:
mov [eax], 4
mov [name],2
mov eax, [ebx]
Tokens: [eax], [ebx]
我可以使用此模式找到我想要的内容:\[(eax|ebx)\]
但是当与其他模式一起使用时出现错误,我相信这是因为'|'。
SCANNER = re.compile(r"""
;(.)* # comment
|(\[-?[0-9]+\]) # memory_int
|(\[-?0x[0-9a-fA-F]+\]) # memory_hex
|(\[(eax|ebx)\]) # memory access with registers
""", re.VERBOSE)
for match in re.finditer(SCANNER, lines[i]):
comment, memory_int, memory_hex, memory_reg = match.groups()
错误:
ValueError: too many values to unpack (expected 4)
有什么方法可以用另一个字符替换 '|'
吗?
我的建议是在解包时忽略该值。
comment, memory_int, memory_hex, memory_reg, _ = match.groups()
或者:
comment, memory_int, memory_hex, memory_reg = match.groups()[:3]
您的心痛是由捕获组中的捕获组引起的,该捕获组导致每个匹配项的 groups()
调用返回一个 5 元组。不要使用捕获组,而是尝试将 非捕获组 (语法:(?:pattern)
)混合到您的最终捕获组中,如下所示:
(\[(?:eax|ebx)\])
示例运行:
>>> SCANNER = re.compile(r';(.)*|(\[-?[0-9]+\])|(\[-?0x[0-9a-fA-F]+\])|(\[(?:eax|ebx)\])')
>>> next(re.finditer(SCANNER, 'mov eax, [ebx]')).groups()
(None, None, None, '[ebx]')
问题不是因为 |
个字符:
|(\[(eax|ebx)\]) # memory access with registers
这是因为表达式的那部分定义了 两个 捕获组,一个嵌套在另一个中 — 所以 match.groups()
返回的值多于可以解包的值,例如作为第一行:
(None, None, None, '[eax]', 'eax')
避免嵌套组的一种方法是改为使用:
|(\[eax\]|\[ebx\]) # memory access with registers
这将导致返回:
(None, None, None, '[eax]')
正如@Shashank 指出的那样,您还可以使用非-捕获组(?:...)
语法来定义嵌套的可能寄存器值模式:
|(\[(?:eax|ebx)\]) # memory access with registers
实现同样的目标。当存在更多可能的子模式(并且它们更复杂)时,这种方法是有利的,因为否则你需要为每种可能性完整地拼出整个模式,而不是利用它们可能具有的一些共性.
我正在尝试在 python 中创建一个编译器,并且我正在使用 re
模块来创建标记。语言将与 Assembly
.
几乎一切正常,但我在使用令牌时遇到问题。让我举例说明这个标记是什么:
mov [eax], 4
mov [name],2
mov eax, [ebx]
Tokens: [eax], [ebx]
我可以使用此模式找到我想要的内容:\[(eax|ebx)\]
但是当与其他模式一起使用时出现错误,我相信这是因为'|'。
SCANNER = re.compile(r"""
;(.)* # comment
|(\[-?[0-9]+\]) # memory_int
|(\[-?0x[0-9a-fA-F]+\]) # memory_hex
|(\[(eax|ebx)\]) # memory access with registers
""", re.VERBOSE)
for match in re.finditer(SCANNER, lines[i]):
comment, memory_int, memory_hex, memory_reg = match.groups()
错误:
ValueError: too many values to unpack (expected 4)
有什么方法可以用另一个字符替换 '|'
吗?
我的建议是在解包时忽略该值。
comment, memory_int, memory_hex, memory_reg, _ = match.groups()
或者:
comment, memory_int, memory_hex, memory_reg = match.groups()[:3]
您的心痛是由捕获组中的捕获组引起的,该捕获组导致每个匹配项的 groups()
调用返回一个 5 元组。不要使用捕获组,而是尝试将 非捕获组 (语法:(?:pattern)
)混合到您的最终捕获组中,如下所示:
(\[(?:eax|ebx)\])
示例运行:
>>> SCANNER = re.compile(r';(.)*|(\[-?[0-9]+\])|(\[-?0x[0-9a-fA-F]+\])|(\[(?:eax|ebx)\])')
>>> next(re.finditer(SCANNER, 'mov eax, [ebx]')).groups()
(None, None, None, '[ebx]')
问题不是因为 |
个字符:
|(\[(eax|ebx)\]) # memory access with registers
这是因为表达式的那部分定义了 两个 捕获组,一个嵌套在另一个中 — 所以 match.groups()
返回的值多于可以解包的值,例如作为第一行:
(None, None, None, '[eax]', 'eax')
避免嵌套组的一种方法是改为使用:
|(\[eax\]|\[ebx\]) # memory access with registers
这将导致返回:
(None, None, None, '[eax]')
正如@Shashank 指出的那样,您还可以使用非-捕获组(?:...)
语法来定义嵌套的可能寄存器值模式:
|(\[(?:eax|ebx)\]) # memory access with registers
实现同样的目标。当存在更多可能的子模式(并且它们更复杂)时,这种方法是有利的,因为否则你需要为每种可能性完整地拼出整个模式,而不是利用它们可能具有的一些共性.