这是日期的一个很好的正则表达式...但是它在我试过的这一页上无限期挂起...我想尝试这个页面(http://pleac.sourceforge.net/pleac_python/datesandtimes.html)因为它确实有很多日期在它上面,我想抓住所有这些。我不明白为什么它在其他页面上没有悬挂...为什么我的正则表达式挂起和/或我怎么能清理它以使它更好/更有效?
Python代码:
monthnames = "(?:Jan\w*|Feb\w*|Mar\w*|Apr\w*|May|Jun\w?|Jul\w?|Aug\w*|Sep\w*|Oct\w*|Nov(?:ember)?|Dec\w*)"
pattern1 = re.compile(r"(\d{1,4}[\/\\\-]+\d{1,2}[\/\\\-]+\d{2,4})")
pattern4 = re.compile(r"(?:[\d]*[\,\.\ \-]+)*%s(?:[\,\.\ \-]+[\d]+[stndrh]*)+[:\d]*[\ ]?(PM)?(AM)?([\ \-\+\d]{4,7}|[UTCESTGMT\ ]{2,4})*"%monthnames, re.I)
patterns = [pattern4, pattern1]
for pattern in patterns:
print re.findall(pattern, s)
btw ...当我说我试图反对这个网站..我正在尝试它反对网页来源。
答案 0 :(得分:5)
您应该阅读Mastering Regular Expressions。问题是:
(?:[\d]*[\,\.\ \-]+)*
需要指数时间。尝试使用:
(?:[\d,. \-]*[,. \-])?
哪个应该匹配相同的东西,但需要线性时间。检查了你的例子,这确实加快了速度。
您似乎也偶然在某个时刻将捕获组引入了您的模式:例如,更改(AM)到(?:AM)来解决这个问题。这将从上面的示例中获取以下输出:
[' Aug 6 20:43:20 2003', ' Mar 14 06:02:55 1973', ' March 14 06:02:55 AM 1973', ' Jun 16 20:18:03 1981']
['2003-08-06', '2003-08-07', '2003-07-23', '1973-01-18', '3/14/1973', '16/6/1981', '16/6/1981', '16/6/1981', '16/6/1981', '08/08/2003']
要深入了解详细信息(我参考的那本书非常擅长),*和+工作(在NFAs中就像python一样),就像一个循环。原始模式的内部循环将匹配一长串数字,但是当后续模式无法匹配时,它将一次“放弃”一个。然后外循环将重新运行剩余模式的内循环,当然它会立即再次抓取数字。每次内循环的一个实例放弃一个数字时,将召唤一个新副本再次抓取它。最终,一旦引擎完成了分割该数字串(指数的可能性)的每种可能方式,它将向前移动一个字符......然后重试。
另一方面,你的模式看起来有点疯狂;)
答案 1 :(得分:0)
Python正则表达式求值程序可能需要很长时间。不幸的是,它在最坏的情况下以指数时间运行。
我认为你的“s”包含整个页面的副本。如果是这样,那么可能会导致正则表达式计算器中出现很长的回溯。也许您应该将页面分成更小的块,并通过正则表达式单独运行它们。您可以使用像beautifulsoup这样的HTML解析器,并分别在每个文本节点上运行正则表达式。这可能会缩短运行时间。
答案 2 :(得分:0)
正则表达式的编写方式将导致批次的回溯。除了关于在较小的文本块上运行它的提示之外,您还可以使用更简单(并且因此更快)的正则表达式来过滤掉无法匹配的文本。
答案 3 :(得分:0)
首先,你应该读一下r""
字符串的意思:你只需要在反斜杠中放入你真正需要反斜杠的东西,所以你的正则表达式应该只是:
monthnames = "(?:Jan\w*|Feb\w*|Mar\w*|Apr\w*|May|Jun\w?|Jul\w?|Aug\w*|Sep\w*|Oct\w*|Nov(?:ember)?|Dec\w*)"
pattern1 = re.compile(r"(\d{1,4}[-/]+\d{1,2}[-/]+\d{2,4})")
pattern4 = re.compile(r"(?:\d*[,. -]+)*%s(?:[,. -]+\d+[stndrh]*)+[:\d]*[ ]?(PM)?(AM)?([ -+\d]{4,7}|[UTCESTGMT ]{2,4})*"%monthnames, re.I)
关于你的真正问题,Python在嵌套在*
内的*
表现不佳。将pattern4更改为此(第一个\d*
变为\d+
):
pattern4 = re.compile(r"(?:\d+[,. -]+)*%s(?:[,. -]+\d+[stndrh]*)+[:\d]*[ ]?(PM)?(AM)?([ -+\d]{4,7}|[UTCESTGMT ]{2,4})*"%monthnames, re.I)
并且正则表达式快速返回,打印出来:
[('', '', '2003'), ('', '', '1973'), ('', 'AM', ' 1973'), ('', '', '1981"')]
['2003-08-06', '2003-08-07', '2003-07-23', '1973-01-18', '3/14/1973', '16/6/1981', '16/6/1981', '16/6/1981', '16/6/1981'
, '08/08/2003']
虽然我不知道这是不是你想要的。