在文件中查找模式匹配的第一个匹配项,然后停止遍历数据

时间:2014-12-02 21:38:35

标签: python regex file

我有一个包含此类数据的文件

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/1986D18/29/1988

我想使用re模块在​​Python中编写它。

4 个答案:

答案 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)

您可以使用其他数据

^D(\d{2}/\d{2}/\d{4})[\s\S]+

Demo

答案 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']