【问题标题】:OR operator inside OR operator - RegEXOR 运算符中的 OR 运算符 - RegEX
【发布时间】:2015-07-08 02:11:39
【问题描述】:

我正在尝试在 python 中创建一个编译器,并且我正在使用re 模块来创建令牌。语言将与Assembly 非常相似。

几乎一切正常,但我遇到了令牌问题。让我举个例子说明这个令牌是什么:

mov [eax], 4
mov [name],2
mov eax, [ebx]

代币:[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)

有没有办法将'|' 替换为另一个字符?

【问题讨论】:

  • 作为非回答评论,我衷心建议您明确而不是隐含地使用re.foo(..., flags=X)。并非所有re 方法都将标志作为第三个变量,因此出于习惯输入flags=X 会让您在某个晚上免于头疼。

标签: python regex string python-3.x token


【解决方案1】:

您的心痛是由捕获组中的捕获组引起的,该捕获组导致每个匹配的 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]')

【讨论】:

    【解决方案2】:

    问题不是因为| 字符:

        |(\[(eax|ebx)\])             # memory access with registers
    

    这是因为表达式的那部分定义了 两个 捕获组,一个嵌套在另一个内部 - 所以match.groups() 返回的值比可以解包的值多,例如第一行:

    (None, None, None, '[eax]', 'eax')
    

    避免嵌套组的一种方法是使用:

        |(\[eax\]|\[ebx\])          # memory access with registers
    

    这将导致返回:

    (None, None, None, '[eax]')
    

    正如@Shashank 指出的,您还可以使用non-capturing group (?:...) 语法来定义嵌套的可能寄存器值模式:

        |(\[(?:eax|ebx)\])          # memory access with registers
    

    达到同样的目的。当存在大量可能的子模式(并且它们更复杂)时,这种方法是有利的,因为否则您需要为每种可能性完整地拼出整个模式,而不是利用它们可能具有的一些共性.

    【讨论】:

      【解决方案3】:

      我的建议是在打开包装时忽略该值。

      comment, memory_int, memory_hex, memory_reg, _ = match.groups()
      

      或者:

      comment, memory_int, memory_hex, memory_reg = match.groups()[:3]
      

      【讨论】:

        猜你喜欢
        • 2014-09-30
        • 2020-10-04
        • 2016-05-31
        • 1970-01-01
        • 1970-01-01
        • 2010-10-23
        • 2016-07-08
        • 2018-04-17
        • 1970-01-01
        相关资源
        最近更新 更多