我有一个包含此类数据的文件
D11/22/1984 D 123 q423 ooo 11/22/1987
R11/22/1985 123 q423 ooo 11/22/1987
D12/24/1986 123 q423 ooo 11/22/1987
511/27/1987 123 q423 ooo 11/22/1987
D18/29/1988 123 q423 ooo 11/22/1987
我需要选择第一次匹配模式^D(\d{2}/\d{2}/\d{4})
的记录,然后中断并停止遍历文件的其余部分。
例如,在上述数据中,我只想选择值D11/22/1984
而不是D12/24/1986
或D18/29/1988
。
我想使用re
模块在Python中编写它。
答案 0 :(得分:2)
你可以在你的文件-obj上构建一个生成器(以下假设它被称为f
),它应用你的re.match
,然后第一次出现匹配,例如:
matches = (re.match('D(\d{2}/\d{2}/\d{4})', line) for line in f)
first_match = next((match.group(1) for match in matches if match), None)
如果您获得None
,则找不到匹配项。您还可以对此进行扩展,以便轻松地执行n
次匹配:
from itertools import islice, ifilter
first5 = list(islice(ifilter(None, matches), 5))
如果您获得一个空列表,则找不到匹配项。
答案 1 :(得分:1)
您可以使用一个函数,该函数使用for循环迭代文件对象,并在找到第一个匹配时返回:
import re
def func():
with open('/path/to/file.txt') as f: # Open the file (auto-close it too)
for line in f: # Go through the lines one at a time
m = re.match('D(\d{2}/\d{2}/\d{4})', line) # Check each line
if m: # If we have a match...
return m.group(1) # ...return the value
迭代文件对象会逐行生成它的行。因此,我们只根据需要检查尽可能多的行。
此外,我从您的模式中删除了^
,因为默认情况下re.match
已经从字符串的开头匹配。
如果您已打开文件对象,只需删除with语句并将该文件作为参数传递给该函数:
import re
def func(f):
for line in f: # Go through the lines one at a time
m = re.match('D(\d{2}/\d{2}/\d{4})', line) # Check each line
if m: # If we have a match...
return m.group(1) # ...return the value
请记住在完成后关闭文件。
答案 2 :(得分:1)
答案 3 :(得分:1)
此正则表达式仅捕获第一次出现:
import re
filedata = '''
D11/22/1984 D 123 q423 ooo 11/22/1987
R11/22/1985 123 q423 ooo 11/22/1987
D12/24/1986 123 q423 ooo 11/22/1987
511/27/1987 123 q423 ooo 11/22/1987
D18/29/1988 123 q423 ooo 11/22/1987
'''
print(list(re.findall(r'^D(\d{2}/\d{2}/\d{4})?.*', filedata, flags=re.M|re.S)))
# ['12/24/1986']
此外,re.search扫描字符串并仅返回找到的第一个匹配项并停止扫描(也许这就是您要查找的内容):
print(re.search(r'^D(\d{2}/\d{2}/\d{4})', filedata, flags=re.M|re.S).groups())
# ('11/22/1984',)
# no need of the (...)?.* Your original pattern can be used.
使用此正则表达式,findall可以找到所有出现的内容:
print(list(re.findall(r'^D(\d{2}/\d{2}/\d{4})', filedata, flags=re.M|re.S)))
# ['11/22/1984', '12/24/1986', '18/29/1988']