代码之家  ›  专栏  ›  技术社区  ›  David Culbreth

蟒蛇回复sub()多行字符串失败

  •  0
  • David Culbreth  · 技术社区  · 6 年前

    import re, sys
    print(sys.version) # so you can see my Python version
    
    repl = (
        "use bravo\\api\\resources\\usersResource;\n"
        "use bravo\\api\\resources\\groupsResource;\n"
        "use bravo\\api\\resources\\bandsResource;\n"
        "use bravo\\api\\resources\\setlistsResource;\n"
        "use bravo\\api\\resources\\songsResource;"
    )
    
    pattern = r'\{\{\$use_table_resources\}\}'
    string = "{{$use_table_resources}}"
    
    re.sub(pattern, repl, string)
    

    无论何时运行它,都会得到以下输出和错误:

    3.6.2 |Anaconda, Inc.| (default, Sep 19 2017, 08:03:39) [MSC v.1900 64 bit (AMD64)]
    Traceback (most recent call last):
      File "test.py", line 15, in <module>
        re.sub(pattern, repl, string)
      File "C:\ProgramData\Anaconda3\lib\re.py", line 191, in sub
        return _compile(pattern, flags).sub(repl, string, count)
      File "C:\ProgramData\Anaconda3\lib\re.py", line 326, in _subx
        template = _compile_repl(template, pattern)
      File "C:\ProgramData\Anaconda3\lib\re.py", line 317, in _compile_repl
        return sre_parse.parse_template(repl, pattern)
      File "C:\ProgramData\Anaconda3\lib\sre_parse.py", line 904, in parse_template
        raise s.error("missing <")
    sre_constants.error: missing < at position 64 (line 2, column 26)
    

    有时当我做这个动作的时候,它会起作用 repl re.sub(...) API

    我知道这个简单的例子不能证明使用regex是合理的,但是这段代码是从一个更大的软件中提取出来的。我不需要任何答案来告诉我regex是错误的方法,因为这实际上是我能产生的最简单的仍然重现问题的例子。在那里 更复杂的情况下,我需要正则表达式来真正完成它的工作。

    不管怎样,我认为问题出在替换字符串的内容上,听起来很奇怪。当我使用较短的替换字符串时,我不会遇到这个错误。

    非常感谢您的指点。这可能是非常微小和愚蠢的东西,但我已经回来了几次,我找不到它。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Jean-François Fabre    6 年前

    替换字符串中没有足够的转义,因此regex引擎将反斜杠解释为捕获组的开始(如经典的 r"\1" "\\1" 没有原始前缀)。

    您可以在每个字符串之前添加原始前缀,但我宁愿使用多行 未经加工的 像这样的字符串(更容易阅读):

    repl = r"""use bravo\\api\\resources\\usersResource;
    use bravo\\api\\resources\\groupsResource;
    use bravo\\api\\resources\\bandsResource;
    use bravo\\api\\resources\\setlistsResource;
    use bravo\\api\\resources\\songsResource;
    """
    

    那么由此产生的替代品就是

    use bravo\api\resources\usersResource;
    use bravo\api\resources\groupsResource;
    use bravo\api\resources\bandsResource;
    use bravo\api\resources\setlistsResource;
    use bravo\api\resources\songsResource;
    

    现在,在不更改输入的情况下:

    使用 re.escape 喜欢 re.sub(pattern, re.escape(repl), string) 因为空格和行尾也会被转义,所以效果不太好

    re.sub(pattern, repl.replace("\\",r"\\"), string)