不要在字符串之前捕获

时间:2017-06-20 10:33:45

标签: python regex

我有一系列令牌可以捕获:

sweet (capture)
SWEETENED (capture)
not sweet (do not capture)
bitterly sweet (do not capture)

现在,我写了这个正则表达式,但它不符合我的要求:

 ^(?!not)^(?!bitterly)(sweet|SWEET|Sweet)(ed|ED)?

此表达式不捕获任何术语。我应该用什么来预测它?

P.S。我正在使用Python

2 个答案:

答案 0 :(得分:3)

方法1:匹配并捕捉您需要的东西,然后匹配其余的

如果在模式中定义了捕获组,则可以使用仅返回捕获组值的re.findall。您只需要匹配您想要忽略的内容,并匹配并捕获您需要获取的内容。但是,当捕获组无法匹配时,它也会返回空元素,这就是为什么filter(None, results)会派上用场。

这是Python snippet

import re
s = '''sweet (capture)
SWEETENED (capture)
not sweet (do not capture)
bitterly sweet (do not capture)'''
print(filter(None, re.findall(r'\b(?:bitterly|not)\s+sweet|\b(sweet\w*)\b', s, flags=re.I)))
# => ['sweet', 'SWEETENED']

下面,

  • \b(?:bitterly|not)\s+sweet - 匹配整个单词bitterlynot,后跟1 +空格和sweet substring
  • | - 或
  • \b(sweet\w*)\b - 一个完整的单词sweet,其后有任何其他单词字符(您可以使用自己的模式代替\w*
  • flags=re.I - 使模式不区分大小写。

请参阅regex demo(只有代码才会保留绿色文本。)

方法2:不允许对输入进行大量控制的Lookbehind

关于消极的后视方法的几句话:在这种情况下我不认为它是好的,因为Python re中的lookbehinds是固定宽度的,并且lookbehind中的所有替代方案必须具有相同的宽度。

您可以使用

(?i)(?<!\bbitterly )(?<!\bnot )\bsweet\w*

(请参阅demo),但如果bitterlysweet之间有2或3个空格,则会失败。

方法3:使用PyPi正则表达式模块的可变宽度后观

另一个有趣的解决方案是使用PyPi正则表达式模块,您可以使用可变宽度的lookbehinds:

import regex
s='''sweet (capture)
SWEETENED (capture)
not sweet (do not capture)
bitterly sweet (do not capture)'''
rx = r'(?<!\b(?:bitterly|not)\s+)\bsweet\w*\b'
print(regex.findall(rx, s, flags=regex.I))
# => ['sweet', 'SWEETENED']

请参阅Python demo on REXTESTER

只有在前面没有sweet模式的情况下,才会匹配整个单词\b(?:bitterly|not)\s+(末尾有任何单词字符)。

答案 1 :(得分:0)

除了@ Wiktor的回答,模仿(*SKIP)(*FAIL)你可能会与否定相处。先行:

(?!.*\b(?:not|bitterly))(?i)sweet(?:ened)?

请参阅a demo on regex101.com

<小时/> 缺点(可能?):notbitterly的位置没有被考虑在内,因此像

这样的句子
sweet and not sour

没有匹配。由你来决定是否需要这个。