“grep C N”的Python等价物?

2024-10-02 02:36:18 发布

您现在位置:Python中文网/ 问答频道 /正文

所以现在我在找一份文件。我得到了一个value变量,它是一个相当长的字符串,有新行等等。然后,我用关于芬德尔(regex,value)查找regex。Regex相当简单-类似于“abcde.*”。在

现在,我不仅要捕获regex所拥有的任何内容,而且还要捕获上下文(与grep-C标志完全相同)。在

所以,假设我将value转储到文件中并对其运行grep,那么我要做的就是grep -C N 'abc de .*' valueinfile

如何在Python中实现相同的功能?我需要答案来使用Unicode regex/text。在


Tags: 文件字符串答案功能内容value标志unicode
2条回答

As recommended通过Ignacio Vazquez-Abrams,使用a deque来存储最后的n行。一旦有许多行出现,popleft为每个新行添加。当正则表达式找到匹配项时,返回堆栈中以前的n行,然后迭代n更多行并同时返回这些行。在

这使您不必在任何行上迭代两次(干),并且只在内存中存储最小的数据。您还提到了对Unicode的需要,因此处理文件编码并向RegEx搜索添加Unicode标志非常重要。另外,另一个答案使用重新匹配()而不是搜索()因此可能产生意想不到的后果。在

下面是一个例子。这个例子只对文件中的每一行迭代一次,这意味着同样包含命中的上下文行将不再被查看。这可能是也可能不是理想的行为,但可以很容易地进行调整,以突出显示或以其他方式在上下文中标记前一次命中的行。在

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import codecs
import re
from collections import deque

def grep(pattern, input_file, context=0, case_sensitivity=True, file_encoding='utf-8'):
    stack = deque()
    hits = []
    lines_remaining = None

    with codecs.open(input_file, mode='rb', encoding=file_encoding) as f:
        for line in f:
            # append next line to stack
            stack.append(line)

            # keep adding context after hit found (without popping off previous lines of context)
            if lines_remaining and lines_remaining > 0:
                continue  # go to next line in file
            elif lines_remaining and lines_remaining == 0:
                hits.append(stack)
                lines_remaining = None
                stack = deque()

            # if stack exceeds needed context, pop leftmost line off stack 
            # (but include current line with possible search hit if applicable)
            if len(stack) > context+1:
                last_line_removed = stack.popleft()

            # search line for pattern
            if case_sensitivity:
                search_object = re.search(pattern, line, re.UNICODE)
            else:
                search_object = re.search(pattern, line, re.IGNORECASE|re.UNICODE)

            if search_object:
                lines_remaining = context

    # in case there is not enough lines left in the file to provide trailing context
    if lines_remaining and len(stack) > 0:
        hits.append(stack)

    # return list of deques containing hits with context
    return hits  # you'll probably want to format the output, this is just an example

我的方法是将文本块拆分为行列表。接下来,遍历每一行,看看是否有匹配项。在匹配的情况下,收集上下文行(发生在当前行之前和之后的行)并返回它。这是我的代码:

import re

def grep(pattern, block, context_lines=0):
    lines = block.splitlines()
    for line_number, line in enumerate(lines):
        if re.match(pattern, line):
            lines_with_context = lines[line_number - context_lines:line_number + context_lines + 1]
            yield '\n'.join(lines_with_context)

# Try it out
text_block = """One
Two
Three
abc defg
four
five
six
abc defoobar
seven
eight
abc de"""

pattern = 'abc de.*'

for line in grep(pattern, text_block, context_lines=2):
    print line
    print ' -'

输出:

^{pr2}$

相关问题 更多 >

    热门问题