Filter the text that appears between two labels

Part 1

Which is the easiest way to create a text filter that only displays text surrounded by two predefined labels. I am not against using any standard tool: sed, awk, python, ...

For example, I would like to see only text surrounded by "Mark Begin" and "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

Part 2

How can I change the solution so that only the last occurrence is written to the output, so for the same input above we get:

output:
Text 4
+3
source share
5 answers
$ 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
+3
source

part 1

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

part 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}
'
+1
source

Functional (stateless) implementation using Python and lazy generators:

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

And now your second request is trivial (see 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
0
source

To display each of them:

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

To output the last

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

I found a good solution:

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

for the second case, but this will require filtering characters.

0
source

Source: https://habr.com/ru/post/1785725/


All Articles