Python re.sub() 多行字符串失败
Python re.sub() failure on multiline string
我有一部分脚本看起来像这样...
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 才能真正完成它的工作。
不管怎样,我认为问题出在替换字符串的内容上,这听起来很奇怪。当我使用较短的替换字符串时,我不会遇到此错误。
非常感谢任何指点。这可能是一件非常微小和愚蠢的事情,但我已经回来过几次了,但我找不到它。
替换字符串中没有足够的转义,因此正则表达式引擎将反斜杠解释为捕获组的开始(就像经典的 r""
或 "\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.sub(pattern, re.escape(repl), string)
一样使用re.escape
效果不佳,因为space和行尾也被转义
但是您可以这样做,因为您知道唯一有问题的字符是反斜杠:
re.sub(pattern, repl.replace("\",r"\"), string)
(用双反斜杠替换反斜杠,输出相同)
我有一部分脚本看起来像这样...
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 才能真正完成它的工作。
不管怎样,我认为问题出在替换字符串的内容上,这听起来很奇怪。当我使用较短的替换字符串时,我不会遇到此错误。
非常感谢任何指点。这可能是一件非常微小和愚蠢的事情,但我已经回来过几次了,但我找不到它。
替换字符串中没有足够的转义,因此正则表达式引擎将反斜杠解释为捕获组的开始(就像经典的 r""
或 "\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.sub(pattern, re.escape(repl), string)
一样使用re.escape
效果不佳,因为space和行尾也被转义
但是您可以这样做,因为您知道唯一有问题的字符是反斜杠:
re.sub(pattern, repl.replace("\",r"\"), string)
(用双反斜杠替换反斜杠,输出相同)