Skip to main content
 首页 » 编程设计

python之匹配直到可选的未转义字符/序列之一或换行符

2025年05月04日9mate10pro

我想匹配一个字符串直到一个终端字符/序列,其中:

  • 终止字符/序列不是匹配项的一部分。
  • 终端字符/序列是定义的集合之一,比方说(',',':', '%%') .
  • 转义的终端字符/模式不作为终止符。
  • 转义的反斜杠将被使用,而不是用于转义后面的字符。
  • 字符串结尾也会终止匹配,即使前面有转义字符也是如此。
  • 换行符 (LF,CR)也充当终止符,即使前面有转义字符。它们也不是匹配的一部分(但如果有的话,最后一个悬空逃逸是)。

所以核心问题是:一些终止符序列被转义中和,而另一些则没有。

这些是一些示例字符串及其所需的匹配结果:字符序列 将被视为原始的,但我正在使用 <newline>对于 (LF,CR) (即对于 U+000A, U+000D 中的原始换行符)

1: xxx\,aaa,bbb --> xxx\,aaa 
2: xxx\\:aaa,bbb --> xxx\\ 
3: xxx\\\\\,aaa\::bbb --> xxx\\\\\,aaa\:  
4: xxx%%aaa --> xxx 
5: xxx\%%aaa --> xxx\%%aaa 
6: xxx%\%bbb\ --> xxx%\%bbb\ 
7: xxx\,aaa<newline>bbb --> xxx\,aaa 
8: xxx\,aaa\<newline>bbb --> xxx\,aaa\ 
 
9: x\xa\a\,bb\\,bb --> x\xa\a\,bb\\ 

按照 SO 上其他一些问题的风格,我设法做到了这一点:

pat = re.compile(r'.+?(?<!\\)(\\\\)*(?=[:,\n\r]|%%|$)', re.DOTALL|re.UNICODE)  

但这并没有涵盖所有规则,它在转义换行符和转义字符串结尾方面存在问题。

编辑: 反斜杠可以出现在任何字符之前而不会导致不匹配(参见示例 9),只是如果它出现在另一个反斜杠之前,它会抵消它作为转义字符的作用,如果它出现在某些终止符之前,它会抵消它们作为终止符的作用。

请您参考如下方法:

这真的很有挑战性。这是我的方法:

import re 
 
l = ['xxx\\,aaa,bbb', 
 'xxx\\\\:aaa,bbb', 
 'xxx\\\\\\\\\\,aaa\\::bbb', 
 'xxx%%aaa', 
 'xxx\\%%aaa', 
 'xxx%\\%bbb\\', 
 'xxx\\,aaa\nbbb', 
 'xxx\\,aaa\nbbb', 
 r'x\xa\a\,bb\\,bb'] 
 
for s in l: 
    print('|||| {0} |||| --> {1}'.format(s, re.match(r'((?:(?:(?:\\\\)+|\\(?:,|:|%)|[^\\,:\n]|\\(?:[^\n]|$))(?<![^\\]%%))*)', s).group(0).rstrip('%'))) 

一些问题:

首先,我不明白你的第六弦。如何将单个反斜杠作为字符串的最后一个字符?这对我来说毫无意义。

其次,我发现很难在不转义任何一个的情况下检查双百分号。后视是无用的,因为我不知道会有多少个反斜杠,也不知道前视,因为它与它们之前的字符不匹配,所以我使用了一种解决方法,即与第一个匹配的后视对并用 rstrip() 删除它.那么它就不是一个纯粹的regex (需要后期处理)但这是我的极限。

最重要部分的解释:

  1. (?:\\\\)+ -- 推进每对反斜杠。
  2. \\(?:,|:|%) -- 推进任何被转义的字符集。
  3. [^\\,:\n] -- 一般规则,除了对这种情况有特殊意义的字符之外的任何字符。
  4. (?<![^\\]%%) -- 当找到一对非转义的 % 时停止.
  5. \\(?:[^\n]|$) -- 匹配后跟非特殊字符或 EOL 的反斜杠。

我将原始字符串放在管道之间以记录换行符。可能它与您的示例中的所有可能性都不匹配,但我希望您能理解。前面的脚本产生:

|||| xxx\,aaa,bbb |||| --> xxx\,aaa 
|||| xxx\\:aaa,bbb |||| --> xxx\\ 
|||| xxx\\\\\,aaa\::bbb |||| --> xxx\\\\\,aaa\: 
|||| xxx%%aaa |||| --> xxx 
|||| xxx\%%aaa |||| --> xxx\%%aaa 
|||| xxx%\%bbb\ |||| --> xxx%\%bbb\ 
|||| xxx\,aaa 
bbb |||| --> xxx\,aaa 
|||| xxx\,aaa 
bbb |||| --> xxx\,aaa 
|||| x\xa\a\,bb\\,bb |||| --> x\xa\a\,bb\\