Отображение данных между двумя фиксированными шаблонами - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть случайные данные, поступающие из источника в файл.Я должен прочитать файл и извлечь только ту часть данных, которая попадает между конкретными шаблонами.

Пример: Предположим, файл myfile.out выглядит следующим образом.

info-data
some more info-data
=================================================================
some-data
some-data
some-data
=================================================================

======================= CONFIG PARMS : ==========================
some-data
some-data
some-data
=================================================================

======================= REQUEST PARAMS : ========================
some-data
some-data
some-data
=================================================================

===================== REQUEST RESULTS ===========================
some-data
=================================================================
some-data
some-data
=================================================================
Data-I-Need
Data-I-Need
...
...
...
Data-I-Need
==========================F I N I S H============================

some-info-data

I 'ищу данные, которые соответствуют только этому конкретному шаблону

=================================================================
Data-I-Need
Data-I-Need
...
...
...
Data-I-Need
==========================F I N I S H============================

Я попытался немного осмотреться, например

Как выбрать линии между двумя шаблонами маркеров, которые могут возникнутьнесколько раз с awk / sed

Bash.Как получить многострочный текст между тегами

Но приведенные там решения awk, sed, похоже, не работают, команды не выдают никаких ошибок или выводов.

Я пробовал это

PATTERN1="================================================================="
PATTERN2="==========================F I N I S H============================"
awk -v PAT1="$PATTERN1" -v PAT2="$PATTERN2" 'flag{ if (/PAT2/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /PAT1/{flag=1}' myfile.out

и

PATTERN1="================================================================="
PATTERN2="==========================F I N I S H============================"
awk  -v PAT1="$PATTERN1" -v PAT2="$PATTERN2" 'PAT1 {flag=1;next} PAT2 {flag=0} flag { print }' file

Может быть, это из-за шаблона?Или я делаю что-то не так.

Скрипт будет работать на RHEL 6.5.

Ответы [ 4 ]

0 голосов
/ 10 ноября 2018

Это может сработать для вас (GNU sed):

sed -r '/^=+$/h;//!H;/^=+F I N I S H=+$/!d;x;s/^[^\n]*\n|\n[^\n]*$//g' file

Хранить строку, содержащую только =, в области удержания (заменяя все, что было раньше). Добавьте все остальные строки для хранения пробела. Если текущая строка не является строкой, содержащей = с последующими F I N I S H с последующими =, удалите ее. В противном случае перейдите в область удержания, удалите первую и последнюю строки и напечатайте остаток.

0 голосов
/ 09 ноября 2018

sed может справиться с этим.

Предполагая, что вы хотите сохранить строки верхнего и нижнего колонтитула -

$: sed -En '/^=+$/,/^=+F I N I S H=+$/ { /^=+$/ { x; d; }; /^[^=]/ { H; d; }; /^=+F I N I S H=+$/{ H; x; p; q; }; }' infile
=================================================================
Data-I-Need
Data-I-Need
...
...
...
Data-I-Need
==========================F I N I S H============================

Если нет, используйте

sed -En '/^=+$/,/^=+F I N I S H=+$/ { /^=+$/ { s/.*//g; x; d; }; /^[^=]/ { H; d; }; /^=+F I N I S H=+$/{ x; p; q; }; }' infile

Обратите внимание, что если вы не используете GNU sed, вам нужно будет вставлять символы новой строки вместо всех этих точек с запятой.

sed -En '
  /^=+$/,/^=+F I N I S H=+$/ {
    /^=+$/ {
      s/.*//g
      x
      d
    }
    /^[^=]/ {
      H
      d
    }
    /^=+F I N I S H=+$/{
      x
      p
      q
    }
}' infile

Data-I-Need
Data-I-Need
...
...
...
Data-I-Need

Разбить его -

sed -En '...'

-En говорит использовать расширенное сопоставление с образцом (-E, которое я действительно использовал только для +), а не выводить что-либо, если не будет задан вопрос (-n).

/^=+$/,/^=+F I N I S H=+$/ {...}

говорит, что выполняет эти команды только между строками, которые являются =, и строками, которые являются =, за исключением F I N I S H где-то посередине. Все вещи между {} будут проверены на всех строках между ними. Это означает, что с первой =+ строки, но это нормально, мы справимся с этим внутри.

(a) /^=+$/ { x; d; };
(b) /^=+$/ { s/.*//g; x; d; };

(a) говорит в каждой из строк, которые являются =, поменять местами (x) текущую строку («пространство образца») с «пробелом удержания», а затем удалить (d) ) образец пространства. Это сохраняет текущую строку и удаляет все, что вы могли накопить выше при фальстартах. (Помните -n не пускает ничего от печати, пока мы этого не хотим.)

(b) говорит, что сначала стереть текущую строку, ТО поменять местами и удалить. Это будет все еще добавлять новую строку. Вы хотели, чтобы это удалили?

/^[^=]/ { H; d; };

Обе версии используют это. В любой строке, которая не начинается с =, добавьте его в область удержания (H), а затем удалите пространство шаблона (d). Удаление всегда перезапускает цикл, читая следующую запись.

(a) /^=+F I N I S H=+$/{ H; x; p; q; };
(b) /^=+F I N I S H=+$/{ x; p; q; };

В любой строке со строкой часового F I N I S H между всеми =, (a) сначала добавит (H) шаблон в область удержания - (b) не будет. Затем оба поменяют местами образец и удерживают пробелы (x), напечатают (p) пространство образца (которое теперь является значением, накопленным в пространстве удержания), а затем удаляют (d) пространство образца, вызывая следующий цикл.

В этот момент вы будете вне первоначального переключения, поэтому, если не произойдет еще одна строка из всех =, вы пропустите все оставшиеся строки. Если он это сделает, он снова начнет накапливать записи, но не распечатает их, пока не достигнет другой записи F I N I S H.

}' infile

Это просто закрывает скрипт и передает имя файла, которое вы использовали. Обратите внимание, что это не редактирование на месте ...

Надеюсь, это поможет.

0 голосов
/ 09 ноября 2018

Хотя там уже есть sed решение, мне нравится sed за его простоту:

sed -n '/^==*\r*$/,/^==*F I N I S H/{H;/^==*[^F=]/h;${g;p}}' file

В этой команде sed мы указали диапазон для запуска наших команд. Этот диапазон начинается со строки, которая начинается, содержит только и заканчивается до =, а затем заканчивается строкой, которая начинается с = и продолжается до F I N I S H. Теперь наши команды:

H добавляет каждую строку немедленно для пробела Затем /^==*[^F=]/h выполняется в верхнем или нижнем колонтитуле других разделов, заменяя удерживающее пространство текущим пространством шаблона.

И в последней строке мы заменяем текущее пространство шаблона на то, что находится в удерживающем пространстве, а затем печатаем его, используя ${g;p}. Все это выводит:

=================================================================
Data-I-Need
Data-I-Need
...
...
...
Data-I-Need
==========================F I N I S H============================
0 голосов
/ 09 ноября 2018

Предполагая, что вам нужны только данные, а не шаблон, используя GNU awk:

awk -v RS='\n={26,}[ A-Z]*={28,}\n' 'RT~/F I N I S H/' file

Разделитель записей RS настроен на совпадение строк с серией = и некоторыми необязательными заглавными символами между ними.

Единственным оператором является проверка, содержит ли терминатор записи RT (текущей записи) ключевое слово FINISH. Если это так, awk напечатает всю запись, состоящую из нескольких строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...