我试图编辑一些试图从一段文本中提取日期的现有正则表达式。由于我对正则表达不太熟悉,我认为这是学习新东西的好时机。
所以我得到了以下正则表达式:
r'\b0*[1-9]?[0-9]\b'
(如果我理解的话)检索一个以0或更多0开头的数字,然后是1到9之间的零个或多个数字,以及0到9之间的1个数字。所以它匹配以下内容: / p>
10
24
01
但它也匹配以下内容(显然不是日期)
94
0000024
虽然它不匹配以下(实际上是日期):
1st
3rd
5th
所以我开始用言语表达我所需要的东西,并尝试在其背后写出正则表达式:
\b|-|\/
[1-9]|0[1-9]|[1-2][0-9]|3[0-1]
st|nd|rd|th|-|\/|\b
将它们放在一起就是:\b|-|\/[1-9]|0[1-9]|[1-2][0-9]|3[0-1]st|nd|rd|th|-|\/|\b
但这似乎根本不起作用。当我测试第二部分(数字)时,它几乎匹配了我输入的所有数字。
我不想将此问题作为give me ze code
问题,但有人可以通过指出我做错了什么来帮助我吗?我真的想学习更多使用正则表达式。
欢迎所有提示!
PS。我知道有些月份的日子少于31天,但我必须开始在某个地方学习......
[编辑]
所以要明确(@Saraiva在评论中要求这样做)。我希望它匹配以下内容:
01
08
9
28
31
2nd
31st
/31st
-22nd/
/25-
但不是这样:
73
01200
026
/2200nd-
(6th
答案 0 :(得分:1)
你的正则表达式片段是正确的,你只是错误地将它们放在一起。如果你这样做:
\b|-|\/[1-9]|0[1-9]|[1-2][0-9]|3[0-1]st|nd|rd|th|-|\/|\b
你正在或(|
)所有东西(所以,你匹配一个单词边界,或一个破折号,或......)。
你想要这样的东西:
(?:\b)(([1-9]|0[1-9]|[1-2][0-9]|3[0-1])(st|nd|rd|th)?)(?:\b|\/)
所以:
a word boundary (non capturing)
followed by a number 0-31
followed (eventually) by one of st nd rd th
followed by a word boundary (non capturing) or a slash
此处示例:https://regex101.com/r/zM4lI5/3
如果切换到使用环视,您可能会获得更好的结果:
(?<=\b|\/|-)((?:[1-9]|0[1-9]|[1-2][0-9]|3[0-1])(?:st|nd|rd|th)?)(?=\b|\/|-)
(?<=\b|\/|-) whatever matches the following, if preceded by this
(?=\b|\/|-) whatever matched the preceding, if followed by this
示例:https://regex101.com/r/zM4lI5/4
编辑:
如果您只想捕获数字,我会改变这样的rexgex,玩非捕获组:
(?<=\b|\/|-)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])(?:st|nd|rd|th)?(?=\b|\/|-)
编辑2:好的,我发现Python要求后视断言具有恒定的长度;在我们的示例中,\b
为0,而\/
和-
为1个字符。如果它对你有好处,我建议只使用空格而不是单词边界:
(?<=\s|\/|-)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])(?:st|nd|rd|th)?(?=\b|\/|-)