Печать после получения всех необходимых полей с помощью awk / sed / bash

Ищем правильный способ печати в нужном формате с помощью awk / sed / bash.

Рассмотрим файл (awk_test.txt) со следующим содержанием:

Checkpoint number: ckpt.123
value1: 10
value2: 10
Checkpoint number: ckpt.234
value1: 20
value2: 25

Как извлечь данные из файла и распечатать их в следующем формате с новой строки?

ckpt.123,10,10
ckpt.234,20,25

Я пробовал использовать следующую команду awk, но не все распечатывает.

awk < awk_test.txt '/ckpt/{a=$NF} /value1/{b=$NF} /value2/{c=$NF} END {printf "%s,%s,%s\n",a,b,c}'
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
161
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вы печатаете данные только в блоке END. Конечно, вам нужен конечный блок, но вам также нужно будет печатать, когда вы дойдете до строки ckpt, и там уже накоплены некоторые данные. Это приводит к:

awk '/ckpt/   { if (a != "") printf "%s,%s,%s\n", a, b, c; a = $NF }
     /value1/ { b = $NF }
     /value2/ { c = $NF }
     END      { printf "%s,%s,%s\n", a, b, c }'

который при использовании с вашими образцами данных дает:

ckpt.123,10,10
ckpt.234,20,25

Или вы даже можете использовать функцию для инкапсуляции печати:

awk 'function print_it() { printf "%s,%s,%s\n", a, b, c; }
     /ckpt/   { if (a != "") print_it(); a = $NF}
     /value1/ { b = $NF }
     /value2/ { c = $NF }
     END      { print_it() }'

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

Для GNU awk в качестве разделителя записей RS можно установить любое регулярное выражение, в этом случае можно установить значение Checkpoint number. Разделитель полей FS может быть установлен на : или \n. Таким образом линии превращаются в поля.

gawk 'BEGIN{ RS = "Checkpoint number" ; FS = ": |\n"; OFS = "," } { if (NR > 1){ print $2,$4,$6 }}' text.txt

Результат:

ckpt.123,10,10
ckpt.234,20,25

ПРИМЕЧАНИЕ: POSIX поддерживает только один символ как RS. Спасибо @EdMorton и @Rafael за ваши комментарии. Я не привык думать о переносимости.

wrt Record Separator RS can be set to any string - нет. В POSIX awks RS - это одиночный символ, а в GNU awk это регулярное выражение с несколькими символами, а не буквальная строка с несколькими символами.

Ed Morton 31.10.2018 05:01

@EdMorton Это определенно важный фактор при рассмотрении вопроса о переносимости. В свою защиту он сослался на gawk и никогда не сказал awk.

Rafael 31.10.2018 05:10

@Rafael Вызов gawk не сообщает читателям, что код будет работать ТОЛЬКО в gawk, он просто сообщает читателю, что плакат просто случайно использовал gawk, и даже в gawk RS - это не «строка», а регулярное выражение.

Ed Morton 31.10.2018 12:14
$ awk '/^Check/{if (NR>1) print rec; rec=$NF; next} {rec = rec "," $NF} END{print rec}' file
ckpt.123,10,10
ckpt.234,20,25

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

sed -r 's/.*: //;N;N;s/\n[^:]*: /,/g' file

Удалите метки и замените символы новой строки запятыми для строк по модулю три.

Другие вопросы по теме