Python 中的正则表达式中的后视断言和负后视断言被打结了
Tied up in knots with lookbehind and negative lookbehind assertions in regular expressions in Python
我有一个 Pandas 数据框,其中有一列字符串数据由正斜杠分隔的两个不同部分组成。我想从字符串的 'right hand side' 中提取文本模式,但如果存在特定的字符串模式则不会。下面这个简单的例子说明了这个问题。
import numpy as np
import pandas as pd
import re
myDF = pd.DataFrame({'pet':['rabbit','mammal/rabbit','mammal/small fluffy rabbit','mammal/lop-eared rabbit','mammal/many rabbits','mammal/jack rabbit']})
因此,数据框如下所示:
pet
0 rabbit
1 mammal/rabbit
2 mammal/small fluffy rabbit
3 mammal/lop-eared rabbit
4 mammal/many rabbits
5 mammal/jack rabbit
我希望能够提取与兔子相关的术语,但前提是它们出现在 /
分隔符的右侧,而不是 rabbit
前面有 jack
(有或没有干预 space)。
我想出的正则表达式是:
rxStr = '(?P<bunny>(?<=/)(?<!jack)(?:.*rabbits?))'
...我希望任何匹配都以 /
开头,但如果以 jack
开头则不需要。但是,它并没有像我希望的那样工作。我尝试了很多变体,但都没有成功。
rxStr = '(?P<bunny>(?<=/)(?<!jack)(?:.*rabbits?))'
rx = re.compile(rxStr,flags=re.I|re.X)
rabbitDF = myDF['pet'].str.extract(rx,expand=True)
myDF = myDF.join(rabbitDF)
print(myDF)
pet bunny
0 rabbit NaN
1 mammal/rabbit rabbit
2 mammal/small fluffy rabbit small fluffy rabbit
3 mammal/lop-eared rabbit lop-eared rabbit
4 mammal/many rabbits many rabbits
5 mammal/jack rabbit jack rabbit
在第 0 行中,正则表达式无法正确找到匹配项,因为没有 /
字符。但是,在第 5 行中,尽管 jack
位于 rabbit
.
之前,但 jack rabbit
还是匹配的
我如何编写一个正则表达式来识别 rabbit
个术语,但前提是前面有 /
而不是前面有 jack
?对于上面给出的正则表达式为何失败的任何解释,我们也将不胜感激。
使用前瞻而不是后视:
myDF.pet.str.extract('(?P<bunny>(?<=/)(?!jack).*rabbit)', expand=True)
bunny
0 NaN
1 rabbit
2 small fluffy rabbit
3 lop-eared rabbit
4 many rabbit
5 NaN
( # capture group
(?<=/) # lookbehind - forwardslash
(?!jack) # negative lookahead - "jack"
.* # match anything
rabbit # match "rabbit"
)
这里,否定前瞻意味着 fwslash 后面不能跟 "jack"。
In [52]: myDF['pet'].str.extract(r'/(?P<bunny>(?!jack).*rabbits?.*)',expand=True)
Out[52]:
bunny
0 NaN
1 rabbit
2 small fluffy rabbit
3 lop-eared rabbit
4 many rabbits
5 NaN
我有一个 Pandas 数据框,其中有一列字符串数据由正斜杠分隔的两个不同部分组成。我想从字符串的 'right hand side' 中提取文本模式,但如果存在特定的字符串模式则不会。下面这个简单的例子说明了这个问题。
import numpy as np
import pandas as pd
import re
myDF = pd.DataFrame({'pet':['rabbit','mammal/rabbit','mammal/small fluffy rabbit','mammal/lop-eared rabbit','mammal/many rabbits','mammal/jack rabbit']})
因此,数据框如下所示:
pet
0 rabbit
1 mammal/rabbit
2 mammal/small fluffy rabbit
3 mammal/lop-eared rabbit
4 mammal/many rabbits
5 mammal/jack rabbit
我希望能够提取与兔子相关的术语,但前提是它们出现在 /
分隔符的右侧,而不是 rabbit
前面有 jack
(有或没有干预 space)。
我想出的正则表达式是:
rxStr = '(?P<bunny>(?<=/)(?<!jack)(?:.*rabbits?))'
...我希望任何匹配都以 /
开头,但如果以 jack
开头则不需要。但是,它并没有像我希望的那样工作。我尝试了很多变体,但都没有成功。
rxStr = '(?P<bunny>(?<=/)(?<!jack)(?:.*rabbits?))'
rx = re.compile(rxStr,flags=re.I|re.X)
rabbitDF = myDF['pet'].str.extract(rx,expand=True)
myDF = myDF.join(rabbitDF)
print(myDF)
pet bunny
0 rabbit NaN
1 mammal/rabbit rabbit
2 mammal/small fluffy rabbit small fluffy rabbit
3 mammal/lop-eared rabbit lop-eared rabbit
4 mammal/many rabbits many rabbits
5 mammal/jack rabbit jack rabbit
在第 0 行中,正则表达式无法正确找到匹配项,因为没有 /
字符。但是,在第 5 行中,尽管 jack
位于 rabbit
.
jack rabbit
还是匹配的
我如何编写一个正则表达式来识别 rabbit
个术语,但前提是前面有 /
而不是前面有 jack
?对于上面给出的正则表达式为何失败的任何解释,我们也将不胜感激。
使用前瞻而不是后视:
myDF.pet.str.extract('(?P<bunny>(?<=/)(?!jack).*rabbit)', expand=True)
bunny
0 NaN
1 rabbit
2 small fluffy rabbit
3 lop-eared rabbit
4 many rabbit
5 NaN
( # capture group
(?<=/) # lookbehind - forwardslash
(?!jack) # negative lookahead - "jack"
.* # match anything
rabbit # match "rabbit"
)
这里,否定前瞻意味着 fwslash 后面不能跟 "jack"。
In [52]: myDF['pet'].str.extract(r'/(?P<bunny>(?!jack).*rabbits?.*)',expand=True)
Out[52]:
bunny
0 NaN
1 rabbit
2 small fluffy rabbit
3 lop-eared rabbit
4 many rabbits
5 NaN