过滤出现在两个标记之间的文本

时间:2011-01-16 12:29:35

标签: python shell text awk filtering

第1部分

创建文本过滤器的最简单方法是什么,该过滤器仅输出由两个预定义标记包围的文本。我不介意使用任何标准工具:sed,awk,python,...

例如,我想只显示“Mark Begin”和“Mark End”包围的文字。

input:
Text 1
Mark Begin
Text 2
Mark End
Text 3
Mark Begin
Text 4
MarK End
Text 4

output:
Text 2
Text 4

第2部分

如何修改解决方案,以便只将最后一次出现写入输出,因此对于上面的相同输入,我们得到:

output:
Text 4

5 个答案:

答案 0 :(得分:3)

$ awk '/Mark End/{f=0}/Mark Begin/{f=1;next}f' file
Text 2
Text 4

$ awk '/Mark End/{f=0}/Mark Begin/{f=1;next}f{p=$0}END{print p}' file
Text 4

答案 1 :(得分:1)

第1部分

awk '
    tolower($0) ~ /mark begin/ {printing = 1; next}
    tolower($0) ~ /mark end/   {printing = 0; next}
    printing                   {print}
'

第2部分

awk '
    tolower($0) ~ /mark begin/ {capturing = 1; text = ""; next}
    tolower($0) ~ /mark end/   {capturing = 0; sep = ""; next}
    capturing                  {text = text sep $0; sep = "\n"}
    END                        {print text}
'

答案 2 :(得分:0)

使用Python和延迟生成器的功能(无状态)实现:

import itertools

def get_lines_between_marks(ilines, start_mark, end_mark):
    for line in ilines:
        if line.strip().lower() == start_mark:
            yield list(itertools.takewhile(lambda s: s.strip().lower() != end_mark, ilines))

for group in get_lines_between_marks(open("file.txt"), "mark begin", "mark end"):
    for line in group:
        print line,
# Text 2
# Text 4

现在你的第二个要求是微不足道的(见iterlast here):

def iterlast(it):
    return reduce(lambda x, y: y, it)

for line in iterlast(get_lines_between_marks(open("file.txt"), "mark begin", "mark end")): 
    print line,
# Text 4

答案 3 :(得分:0)

输出每个:

sed -n '/^Mark Begin$/{:a;n;/^Mark End$/b;p;ba}' inputfile

输出最后一个

sed -n '${x;s/\n//;p};/^Mark Begin$/{x;s/.*//;x;:a;n;/^Mark End$/b;H;ba}'

答案 4 :(得分:0)

我找到了一个很好的解决方案:

awk '/Mark End/, /Mark Begin/' file.lst

对于第二种情况,但毕竟需要标记过滤。