Если еще, Awk NR: Как удалить заголовок раздела таблицы, где нет записей


4

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

Однако в некоторые дни в исходной таблице нет записей больше 30. Когда это происходит, мне не нужен весь раздел, который пуст в сводке. Как мне тогда удалить весь заголовок для этих разделов?

В идеале, если нет записей во всех 5 разделах, не должно быть напечатано ни одной строки (или просто строка, которая говорит: «Нет: нет записи больше 30», как я пытался сделать)

Пример обобщенной таблицы с 5 разделами, summarised_output.txt:

=========================================================================================================
Month: Jun      

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun     

Counter Name                                06/05 14:00     06/05 13:00     06/05 12:00     06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun      

Counter Name                                06/05 10:00     06/05 09:00     06/05 08:00     06/05 07:00
=========================================================================================================


=========================================================================================================
Month: Jun    

Counter Name                                06/05 06:00     06/05 05:00     06/05 04:00     06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun      

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================

Как видите, третий раздел пуст, потому что в файле original_output.txt нет записи выше 30. Но заголовок все еще там.

Мой сводный код (работал):

awk '$1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30' original_output.txt>>summarised_output.txt

Моя попытка удалить заголовок (не работает):

touch summarised_output_temp.txt
awk '{if ($1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30) print $0}' original_output.txt >> summarised_output_temp.txt
if (((wc -l < summarised_output_temp.txt)==42))
then
echo "None: there is no entry larger than 30" >> summarised_output.txt
else
cat output_7_temp.txt>>summarised_output.txt
fi

Ошибка, полученная за попытку:

line 3: ((: (wc -l output_7_temp.txt | awk {print $1})==42: syntax error: invalid arithmetic operator (error token is ".txt | awk {print $1})==42")

Моя простак версия поглазеть 3.1.8
tthhss

Ответы:


1

Если у вас есть GNU awk, вы можете этот скрипт:

awk -v RS='={105}[^=]*={105}' 'NF{print oRT,$0} {oRT=RT}' file

Заголовок таблицы устанавливается как разделитель многострочных записей RS. Он состоит из двух 105 =символов с чем-то промежуточным.

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


Здравствуй! Спасибо за помощь! Я получаю сообщение об ошибке: awk: синтаксическая ошибка рядом со строкой 1 awk: выход из строя рядом со строкой 1. Я думаю, у меня может не быть GNU awk, но я не уверен. я проверил человек AWK , но я не нашел ничего
tthhss

@tthhss Попробуйте использовать gawkвместо awk. Вы также можете выяснить версию, которую вы используете с помощью команды awk --version.
Олив

gawk работал, но в выходном файле изменений нет. Заголовки все еще появились для пустых разделов. может быть, если есть еще способ использования временного файла? Я думал использовать Grep, но не мог найти способ , чтобы включить заголовок , если я искал «SYS.SYS»
tthhss

Я использую GNU awk 4.2.1и заголовок, включая строку 06/05 10:00, не появляется с этим скриптом awk.
Олив

о, это именно то, что я пытаюсь сделать, моя версия gawk 3.1.8. Я пойду искать его и посмотреть , если есть подобная команда для этой версии
tthhss

1

Создайте исполняемый скрипт test.awk, содержащий

awk '
  # { print "read " $0 }
  /^SYS/ {
    if (H) {
      if (F) {print F} else { F="\r\n\r\n"}
      print H; H=""}
    print
    next
  }
  /^./ {
    H=$0
    for (i=1; i<5; i++) {
      getline
      H = H "\r\n" $0
    }
    next
  }
' $@

и беги

test.awk original_output.txt

"/ ^ SYS / {" может быть заменено чем-либо, что распознает строку данных.


Здравствуй! так рад за вашу помощь. Я не знаю почему, но я попытался запустить его, и он возвращает: test.awk: Команда не найдена. Я также добавил первую строку "#! / Usr / bin / awk" после выполнения "which awk", это не помогло.
августа

Каково третье слово моего ответа, если вы пропустили это?
Джерард Х. Пилле

Оно работает! Могу ли я спросить, на что ссылается (i = 1; i <5; i ++)? Я предполагаю, что это 4 строки заголовка?
tthhss

Почти так как есть 5 строк заголовка. Мой скрипт очень слабый, работает только тогда, когда строки данных всегда начинаются с "SYS", и всегда есть ровно 5 строк заголовка. Если вы сможете придумать что-то лучше, чтобы распознать строки данных, я улучшу оба.
Джерард Х. Пилле

1

Эта проблема может быть решена с помощью Perl в этом направлении.

Код

perl -F'/^=+$/m' -lan -0777e '
   my($dashes) = /^(=+)$/m;
   shift @F; pop @F;
   while ( @F > 1 ) {
      my($h, $s) = splice @F, 0, 2;
      next if $s =~ /^(?:\h*\n)+$/;
      print join $dashes, q(), $h, $s, !@F ? q() : ();
   }
' input.txt

Выход

=========================================================================================================
Month: Jun

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/05 14:00     06/05 13:00     06/05 12:00     06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/05 06:00     06/05 05:00     06/05 04:00     06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================

объяснение

  • Отбросьте вход за один раз: опция -0777 для Perl это позволяет.
  • Разбить весь этот файл (теперь он рассматривается как одна длинная строка) вдоль черточек: / ^ = + $ / m означает, что где бы данная строка не содержала ничего, кроме повторяющихся равных, это место, где мы разбиваем файл.
  • -a опция заставит perl заполнить разделенные части в массив @F .
  • Параметр -n для Perl отключит автопечать непосредственно перед чтением следующей записи, а также выполняет цикл, похожий на awk, для записей, считанных с ввода.
  • Сначала мы сохраняем пунктирную линию от входа.
  • Обратите внимание, что операция разбиения сделает первый и последний элементы пустыми, поэтому мы удаляем их из массива @F перед выполнением основной задачи.
  • Мы устанавливаем цикл while, который потребляет 2 элемента ( сращивания ) одновременно из массива @F. Первый - это заголовок, а второй - раздел. Цикл продолжается до тех пор, пока в массиве еще есть как минимум 2 элемента.
  • Ключевым моментом является принятие решения пропустить или не пропустить обработку дуэта заголовка / раздела. И это решается, когда раздел содержит только пустые строки или строки, содержащие только горизонтальные пробелы ( \ h ). Регулярное выражение для этого является / ^ (?: \ H * \ n) + $ /
  • Теперь, если раздел не пустой, остается задача сшить дуэт заголовка / раздела с тире. Мы помним, что при объединении последнего заголовка / раздела нам нужно добавить тире для округления.

1

Похоже на ответ Олив, возможно, немного проще:

gawk -v RS='=+\n' '
    NR % 2 == 0 {header = $0; next}
    /[^[:space:]]/ {printf "%s", RT header RT $0}
    END {print RT}
' output.txt 

Использование строки =s в качестве разделителя записей. Заголовок - это каждая четная запись. И «содержимое» не является пустым, если оно содержит непробельный символ.

RT является специфической переменной GNU awk, содержащей «Входной текст, который соответствует тексту, обозначенному RS, разделителем записей. Он устанавливается каждый раз, когда запись читается».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.