首页 > 解决方案 > 在多行的两个正则表达式模式之间输出文本

问题描述

如果我带入myfile一个可用的环境,我可以运行以下命令python

cat myfile | python filter.py

过滤器.py

import sys

results = []
for line in sys.stdin:
    results.append(line.rstrip("\n\r")) 

start_match = "some text"
lines_to_include_before_start_match = 4
end_match = "some other text"
lines_to_include_after_end_match = 4

for line_number, line in enumerate(results):
    if start_match in line:
        for x in xrange(line_number-lines_to_include_before_start_match, line_number):
            print results[x]

        print line

        for x in xrange(line_number+1, len(results)):       
            if end_match in results[x]:
                print results[x]

                for z in xrange(x+1, x+lines_to_include_after_end_match):
                    print results[z]

                break
            else:
                print results[x]

        print ""

但是我想在其中运行它的环境没有 python。将其转换为我知道环境中存在的 perl 是我唯一的选择吗?是否有简单的 sed 或 awk 命令来执行此操作?

我尝试了以下方法,但它并没有完全给我我正在寻找的东西,因为它错过了 +/- 4 行:

cat myfile | sed -n '/some text/,/some other text/p'

[编辑:python脚本说lines_to_include_after_end_match是4,但实际上它返回3]

标签: pythonawksedgrep

解决方案


鉴于行尾是\n,你可以试试这个:

awk '/some text/{if(l4)printf l4;p=5} /some other text/{e=1} e && p {p--; if (!p) {e=0;l4="";}} !p && !e { l4 = l4 $0 "\n"; sub(/[^\n]*\n(([^\n]*\n){4})/,"\1",l4);} p' file

请注意,如果要在结束匹配后打印额外的 4 行,则标记需要为 6。
我认为您自己的 python 代码只会在结束匹配后打印另外 3 行。

放入几行以增加可红色性:

awk '/some text/{if(l4)printf l4;p=5} 
    /some other text/{e=1} 
    e && p {p--; if (!p) {e=0;l4="";}} 
    !p && !e { l4 = l4 $0 "\n"; sub(/[^\n]*\n(([^\n]*\n){4})/,"\1",l4);} 
    p' file

推荐阅读