Python 确保两个正则表达式不会找到相同的结果
我试图从字符串中解析出所有可能以不同形式书写的日期。问题是,可能有一个日期写在表格d/m-y中,例如22/11-12。但也可以在d/m表中填写日期,但不指定年份。如果我在这个字符串中找到一个包含较长形式的日期,我不希望它以较短形式再次被找到。这就是我的代码失败的地方,它在一年中查找第一个日期两次,在一年中查找一次,在没有它的情况下查找一次 我真的有两个问题:1.什么是正确的方法。我似乎真的从错误的角度来看待这个问题。2如果我坚持这样做,为什么这一行datestring.replacematch.group0不删除日期,这样就无法再次找到我 这是我的代码:Python 确保两个正则表达式不会找到相同的结果,python,regex,Python,Regex,我试图从字符串中解析出所有可能以不同形式书写的日期。问题是,可能有一个日期写在表格d/m-y中,例如22/11-12。但也可以在d/m表中填写日期,但不指定年份。如果我在这个字符串中找到一个包含较长形式的日期,我不希望它以较短形式再次被找到。这就是我的代码失败的地方,它在一年中查找第一个日期两次,在一年中查找一次,在没有它的情况下查找一次 我真的有两个问题:1.什么是正确的方法。我似乎真的从错误的角度来看待这个问题。2如果我坚持这样做,为什么这一行datestring.replacematch.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
dformats = (
'(?P<day>\d{1,2})/(?P<month>\d{1,2}) -(?P<year>\d{2})',
'(?P<day>\d{1,2})/(?P<month>\d{1,2})',
'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})',
)
def get_dates(datestring):
"""Try to extract all dates from certain strings.
Arguments:
- `datestring`: A string containing dates.
"""
global dformats
found_dates = []
for regex in dformats:
matches = re.finditer(regex, datestring)
for match in matches:
# Is supposed to make sure the same date is not found twice
datestring.replace(match.group(0), '')
found_dates.append(match)
return found_dates
if __name__ == '__main__':
dates = get_dates('1/2 -13, 5/3 & 2012-11-22')
for date in dates:
print date.groups()
两种方式:
使用单个正则表达式并使用|运算符将所有事例连接在一起:
expr=re.compile rexpr1 | expr2 | expr3
只查找单个实例,然后传递下一次搜索的开始位置。请注意,这将使事情复杂化,因为无论选择哪种格式,您都希望始终从最早的匹配开始。也就是说,循环所有三个匹配项,找出最早的匹配项,进行替换,然后以递增的起始位置再次进行。这使得选项1变得更加容易
还有几点:
确保使用的是原始字符串:在每个字符串的前面加上一个“r”。否则,\'字符可能会被吃掉,而不会传递给重新引擎
考虑使用sub和回调函数代替repl参数进行替换,而不是使用finditer。在本例中,repl被传递一个匹配对象,并且应该返回替换字符串
如果未选择该备选方案,则单个re中的匹配组将具有“无”值,从而易于检测使用了哪个备选方案
除非您打算修改该变量,否则不应说“全局”
下面是一些完整的工作代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
expr = re.compile(
r'(?P<day1>\d{1,2})/(?P<month1>\d{1,2}) -(?P<year>\d{2})|(?P<day2>\d{1,2})/(?P<month2>\d{1,2})|(?P<year3>\d{4})-(?P<month3>\d{2})-(?P<day3>\d{2})')
def get_dates(datestring):
"""Try to extract all dates from certain strings.
Arguments:
- `datestring`: A string containing dates.
"""
found_dates = []
matches = expr.finditer(datestring)
for match in matches:
if match.group('day1'):
found_dates.append({'day': match.group('day1'),
'month': match.group('month1') })
elif match.group('day2'):
found_dates.append({'day': match.group('day2'),
'month': match.group('month2')})
elif match.group('day3'):
found_dates.append({'day': match.group('day3'),
'month': match.group('month3'),
'year': match.group('year3')})
else:
raise Exception("wtf?")
return found_dates
if __name__ == '__main__':
dates = get_dates('1/2 -13, 5/3 & 2012-11-22')
for date in dates:
print date
两种方式:
使用单个正则表达式并使用|运算符将所有事例连接在一起:
expr=re.compile rexpr1 | expr2 | expr3
只查找单个实例,然后传递下一次搜索的开始位置。请注意,这将使事情复杂化,因为无论选择哪种格式,您都希望始终从最早的匹配开始。也就是说,循环所有三个匹配项,找出最早的匹配项,进行替换,然后以递增的起始位置再次进行。这使得选项1变得更加容易
还有几点:
确保使用的是原始字符串:在每个字符串的前面加上一个“r”。否则,\'字符可能会被吃掉,而不会传递给重新引擎
考虑使用sub和回调函数代替repl参数进行替换,而不是使用finditer。在本例中,repl被传递一个匹配对象,并且应该返回替换字符串
如果未选择该备选方案,则单个re中的匹配组将具有“无”值,从而易于检测使用了哪个备选方案
除非您打算修改该变量,否则不应说“全局”
下面是一些完整的工作代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
expr = re.compile(
r'(?P<day1>\d{1,2})/(?P<month1>\d{1,2}) -(?P<year>\d{2})|(?P<day2>\d{1,2})/(?P<month2>\d{1,2})|(?P<year3>\d{4})-(?P<month3>\d{2})-(?P<day3>\d{2})')
def get_dates(datestring):
"""Try to extract all dates from certain strings.
Arguments:
- `datestring`: A string containing dates.
"""
found_dates = []
matches = expr.finditer(datestring)
for match in matches:
if match.group('day1'):
found_dates.append({'day': match.group('day1'),
'month': match.group('month1') })
elif match.group('day2'):
found_dates.append({'day': match.group('day2'),
'month': match.group('month2')})
elif match.group('day3'):
found_dates.append({'day': match.group('day3'),
'month': match.group('month3'),
'year': match.group('year3')})
else:
raise Exception("wtf?")
return found_dates
if __name__ == '__main__':
dates = get_dates('1/2 -13, 5/3 & 2012-11-22')
for date in dates:
print date
您可以在第二个正则表达式中使用负数前瞻,以仅匹配不后跟-年的日期:-
因此,在第一个正则表达式中匹配的日期将不会在第二个正则表达式中匹配。您可以在第二个正则表达式中使用“负前瞻”来仅匹配那些不后跟-年的日期:-
因此,在第一个正则表达式中匹配的日期将不会在第二个正则表达式中匹配。您可以使用sub代替查找:
您可以使用sub代替查找:
Emacs抱怨您没有遵守pep-8;-否则,这是一个很好的答案。不过,我感到困扰的是,在正则表达式中使用|时,这并不是处理相同组名的简单方法。有6行代码处理这个问题!:-/Niclas:是的,我编辑了大约3次,可能仍然没有弄好:而且,是的,我很沮丧,因为重新引擎不允许我重新使用名称,我可能可以创建一个简单的函数来重新映射以整理代码。如果我们可以假设我们总是将PERIOD-X复制到PERIOD,如果dayX存在,对于范围为1,4的X,以及['day'、'month'、'year']的PERIOD,那么这将只是几行。任何更复杂的处理都可能需要像上面那样解决。@ChrisCogdon是的,如果你使用了很多正则表达式,而不是像我amEmacs抱怨的那样只使用了三个正则表达式,那么你就必须这样做否则,这是一个很好的答案。不过,我感到困扰的是,在正则表达式中使用|时,这并不是处理相同组名的简单方法。有6行代码处理这个问题!:-/尼克拉斯:是的,我编辑了大约3次,可能还是
不正确:另外,是的,我很沮丧,重新引擎不允许我重新使用名称,我可能可以创建一个简单的函数来重新映射以整理代码。如果我们可以假设我们总是将PERIOD-X复制到PERIOD,如果dayX存在,对于范围为1,4的X,以及['day'、'month'、'year']的PERIOD,那么这将只是几行。任何更复杂的处理都可能需要像上面那样解决。@ChrisCogdon是的,如果你使用了很多正则表达式,而不是像我这样只使用了三个正则表达式,你就必须这样做
def find_dates(s):
dformats = (
'(?P<day>\d{1,2})/(?P<month>\d{1,2}) -(?P<year>\d{2})',
'(?P<day>\d{1,2})/(?P<month>\d{1,2})',
'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})',
)
dates = []
for f in dformats:
s = re.sub(f, lambda m: dates.append(m.groupdict()), s)
return dates