【发布时间】:2020-05-01 16:19:08
【问题描述】:
假设我们有一个转义字符 \,它只允许紧跟在另一个 \ 之前。换句话说,转义字符\ 只允许转义自己:\。转义任何其他字符都被认为是不好的转义。
\foo bad escape at position 0
\\foo ok
\\\foo bad escape at position 2
\\\\foo ok
\\\\\foo bad escape at position 4
我需要识别这些不良转义字符、它们的位置以及它们试图转义的内容。我们可以假设输入文本不包含换行符。当然,我可以遍历正确的转义组,直到找到一个错误的转义。
line = '\\\\\\'
i = 0
while i < len(line):
curr_char = line[i]
next_char = line[i+1] if i < len(line) - 1 else 'EOL'
if curr_char == '\\':
if next_char == '\\':
i += 2
continue
else:
print(f'bad escape at pos {i}: {next_char}')
break
else:
i += 1
但我需要一个比这更快的解决方案,这就是为什么我想用正则表达式匹配坏转义。我的第一个 - 有点幼稚 - 方法是匹配任何反斜杠,除了反斜杠之外的任何反斜杠:\\([^\\]|$)。
import re
p = re.compile(r'\\([^\\]|$)')
p.search('\\') # [ok] matches the only backslash
p.search('\\f') # [ok] matches the only backslash
p.search('\\\\') # [err] matches the correctly escaped backslash
p.search('\\\\\\') # [ok] matches the last backslash, which indeed is a bad escape
好吧,那行不通。下一个合乎逻辑的事情似乎是添加一个否定的后向表达式(?<!\\) 以忽略转义的反斜杠。
import re
p = re.compile(r'(?<!\\)\\([^\\]|$)')
p.search('\\') # [ok] matches the only backslash
p.search('\\f') # [ok] matches the only backslash
p.search('\\\\') # [ok] does not match anything
p.search('\\\\\\') # [err] does not match the bad escape (last backslash)
我可以做的另一件事是使用替换并用占位符替换糟糕的转义,但这似乎相当hacky并且不是超级有效......而且,这个解决方案尖叫“必须有更好的方法!” :-)
import re
def f_sub(match):
value = match.group()
if value == '\\\\':
return value
return '\x00'
# bad escape before "with", before "bad" and at the end of the line
line = 'text\\\\line \\with \\\\\\bad escapes\\'
line = re.sub(r'(\\\\)|(\\([^\\]|$))', f_sub, line)
print(line)
'text\\\\line \x00ith \\\\\x00ad escapes\x00'
有人可以帮我解决这个问题吗? 提前非常感谢!
【问题讨论】:
-
如果你直截了当地用另外两个字符替换所有双反斜杠,然后看看是否还剩下单行呢?
-
其实这很有意义!我没有想到这一点。虽然我不想创建一个临时字符串,因为它必须尽可能快。
-
我打赌一个简单的替换然后 find 可以随时击败一个相当复杂的正则表达式。 (当然,你应该计时。)