Печать варьируется от последнего появления определенного узора до первого появления другого узора.

Печать варьируется от последнего появления определенного узора до первого появления другого узора.

Доброе утро, это очень похоже на вопросGrep от последнего вхождения шаблона до другого шаблона(несколько месяцев назад), добавив немного больше деталей.

Я пытаюсь написать скрипт UNIX для файла с несколькими дубликатами шаблонов, за которым следует шаблон, который я ищу. Однако у меня нет 'tac' или 'tail -r' (используя эмулятор UNIX, MKS Toolkit), и я хочу вернуть последнее вхождение Pattern1 перед Pattern2, за которым следуют данные между Pattern1 и Pattern2, а затем также Pattern2. Шаблонами в этом случае будут 'Condition 1' и 'Condition 2':

выход.выход:

...
Condition 1: A
data1
Condition 1: B
data2
Condition 2: C
data3
Condition 1: D
data4
Condition 1: E
data5
Condition 2: F
...

Я хотел бы написать скрипт на awk (или sed, но решил, что awk будет правильным инструментом) для возврата:

Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

Я думаю, что это какая-то форма строки ниже, но я не могу понять синтаксис правильно:

awk '/Condition 1/ {acc = $0;} /,/Condition 2/ {print ?}' output.out

Работа с '/,/', похоже, вызывает у меня зависания. Хотелось бы узнать, есть ли у кого-нибудь совет, буду очень признателен. Большое спасибо за любую помощь и время, потраченное на этот вопрос.

решение1

Пытаться:

$ awk 'f{a=a"\n"$0} /Condition 1/{a=$0; f=1} f && /Condition 2/{print a; f=0}' output.out 
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

Как это работает

  • f{a=a"\n"$0}

    Если переменная fистинна (не равна нулю), то добавить текущую строку в конец переменной a.

  • /Condition 1/{a=$0; f=1}

    Если текущая строка содержит Condition 1, то установите sтекущую строку и установите переменную fв 1.

  • f && /Condition 2/{print a; f=0}

    Если fистинно и текущая строка содержит Condition 2, то вывести переменную aи сбросить fее на ноль.

решение2

Если вам нужна обратная адресация при обработке текста, используйтеex

ЕгоУказано POSIX, и это скриптовая форма viviнепосредственный предшественник ) — очень гибкая.

printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out

Это означает:

Для каждой строки ( gглобально), соответствующей шаблону «Условие 2», выполнить поиск в обратном направлении непосредственно предшествующего экземпляра «Условия 1» и pвывести все строки от этой строки до текущей строки ( .) (то есть строки с «Условием 2»).

Выходные данные на предоставленных входных данных точно такие, как вы описываете.

решение3

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x' infile

хотя это предполагает, что любой строке, которая соответствует, PATTERN_2предшествует по крайней мере одна строка, соответствующая PATTERN_1. Для более общего случая добавьте еще одно условие для проверки PATTERN_1наличия в пространстве шаблона перед печатью:

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x;/PATTERN_1/!d' infile

решение4

Вот зловещий кусочек Perl:

perl -0777 -ne '
    my $c1 = qr/Condition 1/;
    my $c2 = qr/Condition 2/;
    print for map {s/$c2.*?\n\K.*//s; $_}
              grep {/$c2/}
              split /(?=$c1)/ms;
' output.out

Это:

  • читает весь файл (используя параметры -0777и -n),
  • разделяет его там, где появляется Условие 1 ( split),
  • отфильтровывает абзацы, в которых Условие 2 не появляется ( grep),
  • затем удаляет из каждого интересного абзаца все строки, следующие за строкой Условие 2 ( map).

Связанный контент