【问题标题】:Tied up in knots with lookbehind and negative lookbehind assertions in regular expressions in Python在 Python 中的正则表达式中与后向和否定后向断言捆绑在一起
【发布时间】:2018-08-19 06:06:31
【问题描述】:

我有一个 Pandas 数据框,它有一列字符串数据,由正斜杠分隔的两个不同部分组成。我想从字符串的“右侧”提取文本模式,但如果存在特定的字符串模式则不提取。下面这个简单的例子说明了这个问题。

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(有或没有中间空格) )。

我想出的正则表达式是:

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 行,正则表达式正确地找不到匹配项,因为没有 / 字符。但是,尽管 jackrabbit 之前,但在第 5 行中匹配 jack rabbit

我如何编写一个正则表达式来识别rabbit 术语,但前提是前面有/,而不是前面有jack?对于上面给出的正则表达式为何失败的任何解释也将不胜感激。

【问题讨论】:

  • 感谢您的指出 - 我刚刚编辑过。

标签: python regex pandas regex-lookarounds negative-lookbehind


【解决方案1】:
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

RegEx explained ...

【讨论】:

  • 与coldspeed的答案非常相似(即使用负前瞻而不是负后瞻),但不包括分隔符的后向断言。谢谢你的回答。
【解决方案2】:

使用前瞻而不是后瞻:

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”。

【讨论】:

  • 啊,是的,一分钱掉了!非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-17
  • 1970-01-01
  • 2016-05-10
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多