正则表达式意外行为

时间:2016-03-17 00:46:06

标签: python regex python-2.7 python-3.x

我正在研究一个用给定规则翻译给定文本的函数。

def bork(text):
    """
    Implementation of language transformation based on Swedish-Chef talk.
    """

    rules = {"\be": "i",
        "the": "zee",
        "\Be\b": "e-a",
        "an": "un"
        }

    rules = dict((re.escape(k), v) for k, v in rules.items())
    pattern = re.compile("|".join(rules.keys()))
    borked = pattern.sub(lambda i: rules[re.escape(i.group(0))], text.strip())
    return borked

text = """experienced"""
print bork(text)
# gives "experienced"

它应该给"ixperienced"。由于规则\be: i。其他转换在使用较大输入进行测试时效果很好,但是这个失败了,请帮助我。

修改:我添加了规则"\Bi\B": "ee"。哪个应该得到结果"ixpereeenced"。这也没有用。我仍然得到"experienced"

Edit2:似乎问题存在于我使用反斜杠的规则中,但是,我尝试使用原始字符串和re.escape()。之后,我尝试删除re.escape(),但这在字典调用中给出了一个关键错误。(我也想知道为什么会发生这种情况)

3 个答案:

答案 0 :(得分:3)

"\b"是退格字符,ASCII值为8. r"\b"是文字字符\b。使用原始字符串来防止解释转义序列。

rules = {
    r"\be": "i",
    r"the": "zee",
    r"\Be\b": "e-a",
    r"an": "un"
}

然后,摆脱第一个re.escape()电话。

答案 1 :(得分:3)

re.sub的一次传递,使用捕获组,以便我们可以确定在相关区域上匹配的模式。您可以通过保留模式列表来简化subst函数的逻辑,而不是每次都必须枚举rules字典......

rules = {
    r'(\be)'   : 'i',
    r'(the)'   : 'zee',
    r'(an)'    : 'un',
    r'(\Be\b)' : 'e-a'
}
pattern = '|'.join(rules.iterkeys())

def subst(matchobj):
    dind = [ind for (ind, val) in enumerate(matchobj.groups()) if val is not None][0]
    return rules[[val for (ind, val) in enumerate(rules) if ind == dind][0]]

text = 'experienced'
re.sub(pattern, subst, text)

答案 2 :(得分:1)

正则表达式组的顺序很重要。使用“|”时,即使后者在列表中有较长的匹配,也会接受第一个匹配。因此,您不应该依赖dict.keys(),因为订单未定义。使用列表(我想你可以使用有序字典)。此外,matchobject.lastindex返回最后(或唯一)匹配组的索引。

rules = [ 
    (r'\be'  , 'i'  ),
    (r'the'  , 'zee'),
    (r'an'   , 'un' ),
    (r'\Bi\B', 'ee' ),
    (r'\Be\b', 'e-a'  )
]

pattern = '|'.join('({})'.format(rule[0]) for rule in rules)

def subst(matchobj):
    #print(matchobj)
    return rules[matchobj.lastindex-1][1]

text = 'experienced'
re.sub(pattern, subst, text)

返回:

'ixpereeenced'