不区分大小写,仅在Python正则表达式的lookbehind / lookahead组中

时间:2019-03-17 15:10:04

标签: python regex

我了解如何在Python中使匹配大小写不区分大小写,并且了解如何使用前瞻性/后备性,但是如何将两者结合起来?

例如,我的文字是

mytext = I LOVE EATING popsicles at home.

我想从这段文字(我的目标食品)中提取popsicles。此正则表达式效果很好:

import re
regex = r'(?<=I\sLOVE\sEATING\s)[a-z0-9]*(?=\sat\shome)'
re.search(regex, mytext)

但是,我想说明有人写作的情况

i LOVE eating apples at HOME.

应该匹配。但是"I LOVE eating Apples at home"不应该匹配,因为Apples是大写。

因此,我希望在两个(?=\sat\shome)前行和(?<=I\sLOVE\sEATING\s)后行中具有本地区分大小写。我知道我可以对全局不区分大小写使用re.IGNORECASE标志,但是我只希望超前/后退组不区分大小写,而不是我的实际目标表达式。

通常,我会在(?i:I LOVE EATING)之前创建一个不区分大小写的非捕获组,该组能够匹配I LOVE EATINGI love eating。但是,如果我尝试将两者结合在一起:

(?i:<=I\sLOVE\sEATING\s)

我没有匹配项,因为它现在将i:解释为要匹配的文字表达式。有没有一种方法可以将区分大小写的内容与前瞻性内容结合在一起?

编辑:我认为这不是已标记问题的重复。这个问题专门询问一个小组的一部分-我要求一个特定的子集-向前和向后看。这里的语法不同。该其他帖子中的答案并不直接适用。正如该帖子的答案所建议的那样,您需要采取一些变通方法来实现此功能,而这些功能不适用于所谓的重复SO帖子。

3 个答案:

答案 0 :(得分:2)

很遗憾,python re module doesn't allow inline use of mode modifiers in the middle of a regex

作为解决方法,您可以使用以下正则表达式:

reg = re.compile(r'(?<=[Ii]\s[Ll][Oo][Vv][Ee]\s[Ee][Aa][Tt][Ii][Nn][Gg]\s)[a-z0-9]*(?=\s[Aa][Tt]\s[Hh][Oo][Mm][Ee])')

print "Case 1: ", reg.findall('I LOVE Eating popsicles at HOME.')

print "Case 2: ", reg.findall('I LOVE EATING popsicles at home.')

print "Case 3: ", reg.findall('I LOVE Eating Popsicles at HOME.')

输出:

Case 1:  ['popsicles']
Case 2:  ['popsicles']
Case 3:  []

答案 1 :(得分:2)

您可以使用(?i)将正则表达式全局设置为不区分大小写,并使用(?-i:groupcontent)将组切换为不区分大小写:

regex = r'(?i)(?<=I\sLOVE\sEATING\s)(?-i:[a-z0-9]*)(?=\sat\shome)'

您也可以在搜索中使用(?i)代替re.I。以下等效于上述正则表达式:

regex = r'(?<=I\sLOVE\sEATING\s)(?-i:[a-z0-9]*)(?=\sat\shome)'
re.search(regex, mytext, re.I)

答案 2 :(得分:2)

使用(?i:...)可以为正则表达式设置标志(在这种情况下为i本地(内联)用于正则表达式的某些部分。

在lookbehind或 先行,同时保持其余正则表达式不带任何选择。

我修改了您的代码,因此它会一次编译正则表达式 对于不同的字符串,调用次数是2次:

mytext1 = 'i LOVE eating Apples at HOME.'
mytext2 = 'i LOVE eating apples at HOME.'
pat = re.compile(r'(?<=(?i:I\sLOVE\sEATING\s))[a-z0-9]+(?=(?i:\sAT\sHOME))')
m = pat.search(mytext1)
print('1:', m.group() if m else '** Not found **')
m = pat.search(mytext2)
print('2:', m.group() if m else '** Not found **')

它打印:

1: ** Not found **
2: apples

因此匹配项仅适用于第二个源字符串。