Фильтр текста, который появляется между двумя отметками - PullRequest
3 голосов
/ 16 января 2011

часть 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 ]

3 голосов
/ 16 января 2011
$ 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 голос
/ 16 января 2011

часть 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}
'
0 голосов
/ 07 января 2013

Я нашел хорошее решение:

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

для второго случая, но все-таки потребуется фильтрация меток

0 голосов
/ 16 января 2011

Для вывода каждого:

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}'
0 голосов
/ 16 января 2011

Функциональная (без состояния) реализация, использующая 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

А теперь ваш второй запрос тривиален (см. Здесь здесь ):

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
...