python正则表达式,在多行匹配,但仍想获得行号

Lar*_*Cai 10 python regex parsing

我有很多日志文件,并希望使用多行搜索某些模式,但为了轻松找到匹配的字符串,我仍然希望看到匹配区域的行号.

任何好的建议.(代码示例被复制)

string="""
####1
ttteest
####1
ttttteeeestt

####2

ttest
####2
"""

import re
pattern = '.*?####(.*?)####'
matches= re.compile(pattern, re.MULTILINE|re.DOTALL).findall(string)
for item in matches:
    print "lineno: ?", "matched: ", item
Run Code Online (Sandbox Code Playgroud)

[UPDATE] lineno是实际的行号

所以我想要的输出看起来像:

    lineno: 1, 1
    ttteest
    lineno: 6, 2
    ttttteeeestt
Run Code Online (Sandbox Code Playgroud)

him*_*har 6

您可以预先存储行号,然后查找它.

import re

string="""
####1
ttteest
####1
ttttteeeestt

####2

ttest
####2
"""

end='.*\n'
line=[]
for m in re.finditer(end, string):
    line.append(m.end())

pattern = '.*?####(.*?)####'
match=re.compile(pattern, re.MULTILINE|re.DOTALL)
for m in re.finditer(match, string):
    print 'lineno :%d, %s' %(next(i for i in range(len(line)) if line[i]>m.start(1)), m.group(1))
Run Code Online (Sandbox Code Playgroud)


mel*_*wil 5

你想要的是正则表达不是很擅长的典型任务; 解析.

您可以逐行读取日志文件,并在该行中搜索您用于分隔搜索的字符串.您可以逐行使用正则表达式,但它比常规字符串匹配效率低,除非您正在寻找复杂的模式.

如果你正在寻找复杂的比赛,我希望看到它.####如果没有正则表达式,搜索文件中的每一行以保持行数都会更容易.


ide*_*n42 5

这可以通过以下方式相当有效地完成:

  • 查找所有匹配项
  • 循环换行,将{offset: line_number}映射存储到最后一次匹配。
  • 对于每个匹配项,预先反向查找第一个换行符的偏移量并在地图中查找它的行号。

这避免了每次匹配都从文件的开头开始计数。

下面的函数类似于 re.finditer

def finditer_with_line_numbers(pattern, string, flags=0):
    '''
    A version of 're.finditer' that returns '(match, line_number)' pairs.
    '''
    import re

    matches = list(re.finditer(pattern, string, flags))
    if not matches:
        return []

    end = matches[-1].start()
    # -1 so a failed 'rfind' maps to the first line.
    newline_table = {-1: 0}
    for i, m in enumerate(re.finditer(r'\n', string), 1):
        # don't find newlines past our last match
        offset = m.start()
        if offset > end:
            break
        newline_table[offset] = i

    # Failing to find the newline is OK, -1 maps to 0.
    for m in matches:
        newline_offset = string.rfind('\n', 0, m.start())
        line_number = newline_table[newline_offset]
        yield (m, line_number)
Run Code Online (Sandbox Code Playgroud)

如果需要内容,可以将最后一个循环替换为:

    for m in matches:
        newline_offset = string.rfind('\n', 0, m.start())
        newline_end = string.find('\n', m.end())  # '-1' gracefully uses the end.
        line = string[newline_offset + 1:newline_end]
        line_number = newline_table[newline_offset]
        yield (m, line_number, line)
Run Code Online (Sandbox Code Playgroud)

请注意,最好避免从 中创建列表finditer,但这意味着我们不知道何时停止存储换行符(即使唯一的模式匹配位于文件的开头,它也可能最终存储许多换行符) )

如果避免存储所有匹配项很重要 - 可以制作一个迭代器来根据需要扫描换行符,尽管不确定这在实践中会给您带来多大优势。