意外的re.sub行为

时间:2016-12-03 11:44:44

标签: python regex

我定义了

s='f(x) has an occ of x but no y'
def italicize_math(line):
    p="(\W|^)(x|y|z|f|g|h)(\W|$)"
    repl=r"\1<i>\2</i>\3"
    return re.sub(p,repl,line)

并拨打以下电话:

print(italicize_math(s)

结果是

'<i>f</i>(x) has an occ of <i>x</i> but no <i>y</i>'

这不是我的预期。我想要这个:

'<i>f</i>(<i>x</i>) has an occ of <i>x</i> but no <i>y</i>'

任何人都可以告诉我为什么x的第一次出现没有包含在&#34; i&#34;标签

3 个答案:

答案 0 :(得分:4)

当您真正想要一个单词边界(\W)时,您似乎试图匹配非字母数字字符(\b):

>>> p=r"(\b)(x|y|z|f|g|h)(\b)"
>>> re.sub(p,repl,s)
'<i>f</i>(<i>x</i>) has an occ of <i>x</i> but no <i>y</i>'

当然,( 非字母数字 - 内部内容不匹配的原因是因为\W消耗了匹配中的字符。所以使用'f(x)'之类的字符串,匹配(时匹配f。由于(已匹配,因此当您尝试匹配x时,它将无法与再次匹配。相比之下,单词边界不会消耗任何字符。

答案 1 :(得分:3)

因为组构造首先匹配字符串开头的位置,x将与前一个匹配重叠。此外,第一组和第三组是冗余的,因为它们可以被字边界取代;你可以利用一个字符组来组合字母。

p = r'\b([fghxyz])\b'
repl = r'<i>\1</i>'

答案 2 :(得分:1)

与先前的回答提及一样,因为匹配listConfig: { itemTpl: '<div data-qtip="{description}">{name}</div>' }; 时消耗的(字符会导致后续f失败。

除了用单词边界x替换之后,您还可以使用前瞻性正则表达式,它只是一瞥并且不会消耗前瞻中的任何匹配。由于它没有消耗任何东西,你不需要\b

\3