首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >匹配直到另一个未转义的字符/序列或换行符

问匹配直到另一个未转义的字符/序列或换行符
EN

Stack Overflow用户
提问于 2013-09-11 08:48:10
回答 2查看 332关注 0票数 2

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

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

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

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

代码语言:javascript
复制
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\\

按照这里提出的其他一些问题的风格,我设法做到了以下几点:

代码语言:javascript
复制
pat = re.compile(r'.+?(?<!\\)(\\\\)*(?=[:,\n\r]|%%|$)', re.DOTALL|re.UNICODE) 

但是这并不包括所有的规则,它在转义换行符和字符串结束时有问题。

编辑:反斜杠可以发生在任何字符之前而不会造成不匹配(参见示例9),只是如果它发生在另一个反斜杠之前,它会中和它作为转义字符的效果,如果它发生在某些终止符之前,则会中和它们作为终止符的效果。

EN

回答 2

Stack Overflow用户

发布于 2013-09-11 10:42:00

这真的很有挑战性。在这里,我的方法:

代码语言:javascript
复制
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。

我把原来的字符串放在管道之间,以注意换行符。也许它并不能与你的例子中的每一种可能性相匹配,但我希望你能理解这个想法。前面的脚本产生了:

代码语言:javascript
复制
|||| 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\\
票数 1
EN

Stack Overflow用户

发布于 2013-09-12 23:12:19

OP:

找到了一种简单的方法:枚举所有法律案件,而不是试图匹配终止符:

代码语言:javascript
复制
import re

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

patver = re.compile(r'''(
[^,:\n\r%\\]  | # generic: consume any non-special char
\\[^\n\r]     | # consume any escaped char - enc '%' and backslash
%(?!%)        | # two successive '%', no need for lookbehind because of previous term 
\\(?=\n|\r|$) | # dangling backslash
)*''', re.DOTALL|re.VERBOSE)

l = [r'xxx\,aaa,bbb',
 r'xxx\\:aaa,bbb',
 r'xxx\\\\\,aaa\::bbb',
 r'xxx%%aaa',
 r'xxx\%%aaa',
 'xxx%\\%bbb\\',
 'xxx\\,aaa\nbbb',
 'xxx\\,aaa\\\nbbb',
 r'x\xa\a\,bb\\,bb',
 r'xxx\\%%bbb',
 r'xxx\%%%bbb',
     ]

for s in l:
    print('|||| {0} |||| --> {1}'.format(s, re.match(pat, s).group(0)))

这种方法对长终止符序列是不实用的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18736593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档