代码之家  ›  专栏  ›  技术社区  ›  anon

为什么Python中的re.sub不能在这个测试用例上正常工作?

  •  3
  • anon  · 技术社区  · 14 年前

    试试这个代码。

    test = ' az z bz z z stuff z  z '
    re.sub(r'(\W)(z)(\W)', r'\1_\2\3', test)
    

    这应该用z代替所有独立的z

    然而,结果是:

    “az-z-bz-z东西”

    你看,那里少了一个z。我认为这是因为分组不能同时获取z之间的空格来匹配两个z(一个用于尾随空格,一个用于前导空格)。有办法解决这个问题吗?

    4 回复  |  直到 14 年前
        1
  •  4
  •   Chris Morgan    14 年前

    这样做的原因是您得到了一个重叠的匹配;您需要不匹配额外的字符-有两种方法可以做到这一点;一种是使用 \b ,单词boundary,如其他人所建议的,另一个使用 后视断言 以及 前瞻性断言 . (如果合理的话,可能应该使用 \乙 而不是这个解决方案。这主要是为了教育目的。)

    >>> re.sub(r'(?<!\w)(z)(?!\w)', r'_\1', test)
    ' az _z bz _z _z stuff _z  _z '
    

    (?<!\w) 确保没有 \w 以前。

    (?!\w) 确保没有 \西 之后。

    特别的 (?...) 语法意味着它们不是组,所以 (z) \1 .


    至于失败原因的图形解释:

    regex将遍历字符串进行替换;它位于以下三个字符处:

    ' az _z bz z z stuff z  z '
              ^^^
    

    它做那个替换。最后的角色已经被执行了,所以它的下一步大致是这样的:

    ' az _z bz _z z stuff z  z '
                  ^^^ <- It starts matching here.
                 ^ <- Not this character, it's been consumed by the last match
    
        2
  •  6
  •   John Kugelman    14 年前

    如果你的目标是确保你只匹配 z 当它是一个独立的单词时,使用 \b 要匹配单词边界而不实际使用空白:

    >>> re.sub(r'\b(z)\b', r'_\1', test)
    ' az _z bz _z _z stuff _z  _z '
    
        3
  •  5
  •   Avi    14 年前

    您希望避免捕获空白。尝试使用0宽分词 \b ,就像这样:

    re.sub(r'\bz\b', '_z', test)
    
        4
  •  1
  •   Ruel    14 年前

    使用这个:

    test = ' az z bz z z stuff z  z '
    re.sub(r'\b(z)\b', r'_\1', test)