Python,使用正则表达式排除数字匹配

3

使用正则表达式从字符串中提取长度大于2的任何数字,但也要排除“2016”,这是我所拥有的:

import re

string = "Employee ID DF856, Year 2016, Department Finance, Team 2, Location 112 "

print re.findall(r'\d{3,}', string)

输出:

['856', '2016', '112']

我试图将其更改为以下内容,以排除“2016”,但所有尝试都失败了。
print re.findall(r'\d{3,}/^(!2016)/', string)
print re.findall(r"\d{3,}/?!2016/", string)
print re.findall(r"\d{3,}!'2016'", string)

什么是正确的方法?谢谢。

问题已经扩展,请查看Wiktor Stribiżew最后发表的评论进行更新。

3个回答

1

你想使用负向先行断言。正确的语法如下:

\D(?!2016)(\d{3,})\b

结果为:

In [24]: re.findall(r'\D(?!2016)(\d{3,})\b', string)
Out[24]: ['856', '112']

或者使用负回顾后断言:
In [26]: re.findall(r'\D(\d{3,})(?<!2016)\b', string)
Out[26]: ['856', '112']

感谢您的帮助和多次编辑。希望您不介意我选择了另一个提供更详细解决方案的答案。我已经为您的回答点赞了。 :) - Mark K
1
@MarkK 另外,这个解决方案对于字符串开头的数字是不起作用的。 - Wiktor Stribiżew
但是你可以通过一些更改使其适用于以起始数字开头的情况:(?:\D|^)(?!2016\b)(\d{3,})。另外,关于回顾后发版本,请注意它匹配类似于102016的内容。 - bobble bubble

1

你可以使用

import re
s = "Employee ID DF856, Year 2016, Department Finance, Team 2, Location 112 20161 12016 120162"
print(re.findall(r'(?<!\d)(?!2016(?!\d))\d{3,}', s))

查看Python演示正则表达式演示

详情

  • (?<!\d) - 当前位置左侧不允许有数字
  • (?!2016(?!\d)) - 当前位置右侧不允许出现2016,且后面没有其他数字
  • \d{3,} - 三个或更多数字。

另一种带有代码的替代方案:

import re
s = "Employee ID DF856, Year 2016, Department Finance, Team 2, Location 112 20161 12016 120162"
print([x for x in re.findall(r'\d{3,}', s) if x != "2016"])

在这里,我们提取任何由3个或更多数字组成的块(re.findall(r'\d{3,}', s)),然后过滤掉等于2016的那些。

先生,感谢您的分享和帮助。另一种解决方案是婴儿般的方式,非常棒! - Mark K
1
@MarkK 好吧,我只是想展示如何使用单个 re.findall 调用完成,但有人不喜欢我的想法。无论如何,我打算添加第二个解决方案,只是有些人倾向于抱怨非正则表达式答案用于正则表达式问题。反之亦然 :) 我们不能取悦 SO 上的每个人。 - Wiktor Stribiżew
先生,有没有一种正则表达式的方法可以从提取中排除“2017”、“2016”和任何“000”这样的数字?谢谢。 - Mark K
1
@MarkK 有两种方法。如果您使用第一种解决方案,请将这些模式添加到负向先行断言中:r'(?<!\d)(?!(?:201[67]|000)(?!\d))\d{3,}'。如果您使用第二个,if x not in ['2016', '2017', '000'] 或者其他(您甚至可以在那里使用另一个简单的正则表达式)。我实际上不太明白您所说的“类似000的数字”。如果您想匹配4位或更多位数的数字,请在主模式中使用\d{4,} - Wiktor Stribiżew
太棒了,先生!无法想象如果没有像您这样鼓励和分享精神的人,人类历史将会倒退多少年! - Mark K

1
另一种方法可以是:

这样做的另一种方式可以是:

st="Employee ID DF856, Year 2016, Department Finance, Team 2, Location 112 "
re.findall(r"\d{3,}",re.sub("((2)?(016))","",st))

输出将会是:
['856', '112']

但是我看到被接受的答案比我的建议更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接