grep, sed, awk, perl: получить раздел из файла на основе идентификатора внутри раздела

От человека 7 сигнал:

The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

0
07.05.2020, 13:08
1 ответ

Это отчасти зависит от того, насколько «хорошо -оформлен» ваш документ. Если вы уверены, что каждому SECTIONсоответствует ENDSECTION, то следующий код awkдолжен работать, хотя я бы не назвал его «одним -лайнером» (и я не уверен это возможно в первую очередь ).

awk -v pat='id=foo' '/^SECTION/{n=f=0; delete buf;} \
 {buf[++n]=$0; if (index($0,pat)) f=1} \
 /^ENDSECTION/ {if (f) for (i=1;i<=n;i++) print buf[i]}' input.txt
  • Шаблон поиска будет тем, что вы назначите pat(, но в текущей форме он выполняет только фиксированный -строковый поиск, а не поиск на основе регулярного выражения -).
  • Когда найдена строка, начинающаяся сSECTION(или любого другого ключевого слова ), флагf(для «найдено» )и счетчик строк nинициализируются нулем. Кроме того, поскольку нам нужно буферизовать весь раздел, поскольку решение о печати может быть принято только после завершения раздела, мы очищаем переменную буфера buf.
  • Для любой строки (, включая пустые в данном случае ), счетчик строки nувеличивается, а строка добавляется в переменную массива buf. Если шаблон найден в строке, флаг fустанавливается в 1.
  • Если ключевое слово ENDSECTIONнаходится в начале строки, а флаг fравен 1, буфер печатается построчно для вывода соответствующего раздела.

Если бы вы могли гарантировать, что все разделы разделены пустыми строками, этот ответ мог бы указать вам правильное направление в том, как сделать это с меньшим количеством кода, но если это не гарантируется, "абзац режим" подход awkне будет работать.

Также заметьте, что это предложение является минимумом, необходимым для выполнения задачи; если вы хотите пропустить пустые строки или выполнить другие требования проверки работоспособности, код быстро станет довольно длинным.

1
28.04.2021, 23:16

Теги

Похожие вопросы