不在字符串之前捕获

2024-10-06 07:18:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一系列的标记要捕获:

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

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

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

此表达式不包含任何术语。我应该用什么展望来捕捉这个?你知道吗

另外,我用Python来做这个


Tags: 标记表达式notdocapture术语sweeted
2条回答

方法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子字符串
  • |-或
  • \b(sweet\w*)\b-一个完整的单词sweet,后面有任何其他单词字符(您可以使用自己的模式而不是\w*
  • flags=re.I-使模式不区分大小写。你知道吗

参见regex demo(由于代码的缘故,绿色文本将被保留)。你知道吗

方法2:lookbehind不允许对输入进行太多控制

关于消极的lookbehind方法的几句话:我认为这种方法不好,因为Pythonre中的lookbehind是固定宽度的,lookbehind中的所有替代方法必须具有相同的宽度。你知道吗

你可以用

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

(参见demo),但是如果在bitterlysweet之间有2或3个空格,则会失败。你知道吗

方法3:使用PyPi regex模块的可变宽度lookback

另一个有趣的解决方案是使用PyPi regex模块,您可以在其中使用可变宽度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。你知道吗

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

除了@Wiktor模仿(*SKIP)(*FAIL)的答案之外,你可能还和neg相处得很好。展望:

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

a demo on regex101.com


缺点(也许?):不考虑notbitterly的位置,因此
sweet and not sour

不会匹配的。由你来决定是否需要这样做。你知道吗

相关问题 更多 >