Синтез по умолчанию Соляной выход высокого состояния - PullRequest
2 голосов
/ 17 мая 2019

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

Какой самый лучший способ преобразовать Сводку во что-то машиночитаемое?

Summary for app1.domain.com
--------------
Succeeded: 278 (unchanged=12, changed=6)
Failed:      0
--------------
Total states run:     278
Total run time:     7.383 s
--
Summary for app2.domain.com
--------------
Succeeded: 278 (unchanged=12, changed=6)
Failed:      0
--------------
Total states run:     278
Total run time:     7.448 s
--
Summary for app0.domain.com
--------------
Succeeded: 293 (unchanged=13, changed=6)
Failed:      0
--------------
Total states run:     293
Total run time:     7.510 s

Без лучшей идеи я пытаюсь grep и awk вывод и вставить его в CSV.

Эти две работы:

cat ${_FILE} | grep Summary | awk '{ print $3} ' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate.csv;

cat ${_FILE} | grep -oP '(?<=unchanged=)[0-9]+' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate.csv;

Но этот не работает, но работает в Reger

cat ${_FILE} | grep -oP '(?<=\schanged=)[0-9]+' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate.csv;

EDIT1: @vintnes @ikegami Я согласен, что я бы предпочел использовать вывод json для анализа вывода, но Salt не предлагает сводку изменений при выводе в josn. Пока что это то, что у меня есть, и хотя оно очень уродливо, оно работает.

cat ${_FILE} | grep Summary | awk '{ print $3} ' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate_tmp.csv;

cat ${_FILE} | grep -oP '(?<=unchanged=)[0-9]+' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate_tmp.csv;

cat ${_FILE} | grep unchanged | awk -F' ' '{ print $4}' | \
    grep -oP '(?<=changed=)[0-9]+' | tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate_tmp.csv;

cat ${_FILE} | { grep "Warning" || true; } | awk -F: '{print $2+0} END { if (!NR) print "null" }' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate_tmp.csv;

cat ${_FILE} | { grep "Failed" || true; } | awk -F: '{print $2+0} END { if (!NR) print "null" }' | \
    tr '\n' ',' | sed '$s/,$/\n/' >> /tmp/highstate_tmp.csv;

csvtool transpose /tmp/highstate_tmp.csv > /tmp/highstate.csv;

sed -i '1 i\instance,unchanged,changed,warning,failed' /tmp/highstate.csv;

Выход:

instance,unchanged,changed,warning,failed
app1.domain.com,12,6,,0
app0.domain.com,13,6,,0
app2.domain.com,12,6,,0

Ответы [ 3 ]

2 голосов
/ 17 мая 2019
perl -e'
   use strict;
   use warnings qw( all );

   use Text::CSV_XS qw( );

   my $csv = Text::CSV_XS->new({ auto_diag => 2, binary => 1 });
   $csv->say(select(), [qw( instance unchanged change warning failed )]);

   my ( $instance, $unchanged, $changed, $warning, $failed );
   while (<>) {
      if (/^Summary for (\S+)/) {
         ( $instance, $unchanged, $changed, $warning, $failed ) = $1;
      }
      elsif (/^Succeeded:\s+\d+ \(unchanged=(\d+), changed=(\d+)\)/) {
         ( $unchanged, $changed ) = ( $1, $2 );
      }
      elsif (/^Warning:\s+(\d+)/) {
         $warning = $1;
      }
      elsif (/^Failed:\s+(\d+)/) {
         $failed = $1;
         $csv->say(select(), [ $instance, $unchanged, $changed, $warning, $failed ]);
      }
   }
'

Укажите входные данные через STDIN или укажите путь к файлу (файлам), из которого нужно считывать аргументы.


Краткая версия:

perl -MText::CSV_XS -ne'
   BEGIN {
      $csv = Text::CSV_XS->new({ auto_diag => 2, binary => 1 });
      $csv->say(select(), [qw( instance unchanged change warning failed )]);
   }
   /^Summary for (\S+)/ and @row=$1;
   /^Succeeded:\s+\d+ \(unchanged=(\d+), changed=(\d+)\)/ and @row[1,2]=($1,$2);
   /^Warning:\s+(\d+)/ and $row[3]=$1;
   /^Failed:\s+(\d+)/ and ($row[4]=$1), $csv->say(select(), \@row);
'
1 голос
/ 17 мая 2019

Вот, пожалуйста.Это также будет работать, если ваш вывод содержит предупреждения.Обратите внимание, что вывод в другом порядке, чем вы указали;это порядок, в котором каждая запись встречается в файле.Не стесняйтесь с любыми вопросами.

$ awk -v OFS=, '
        BEGIN        { print "instance,unchanged,changed,warning,failed" }
        /^Summary/   { instance=$NF }
        /^Succeeded/ { split($3 $4 $5, S, /[^0-9]+/) }
        /^Failed/    { print instance, S[2], S[3], S[4], $2 }
' "$_FILE"
  • split($3 $4 $5, S, /[^0-9]+/) обрабатывает возможность предупреждений, игнорируя первые два «слова» Succeeded: ### и используя любое количество нецифровых символов в качестве разделителя,

edit: Напечатано на /^Fail/ вместо использования /^Summ/ и END.

0 голосов
/ 18 мая 2019

Улучшение ответа от @vintnes. Вывод результатов в виде разделенных табуляцией CSV

Напишите скрипт awk, который читает значения из строк по их порядку. Напечатайте каждую запись в том виде, в котором она прочитана.

script.awk

BEGIN {print("computer","succeeded","unchanged","changed","failed","states run","run time");}
FNR%8 == 1 {arr[1] = $3}
FNR%8 == 3 {arr[2] = $2; arr[3] = extractNum($3); arr[4] = extractNum($4)}
FNR%8 == 4 {arr[5] = $2;}
FNR%8 == 6 {arr[6] = $4;}
FNR%8 == 7 {arr[7] = $4; print arr[1],arr[2],arr[3],arr[4],arr[5],arr[6],arr[7];}

function extractNum(str){match(str,/[[:digit:]]+/,m);return m[0];}

скрипт запуска

Выход CSV с разделением табуляцией

awk -v OFS="\t" -f script.awk input-1.txt input-2.txt ...

Выход CSV через запятую

awk -v OFS="," -f script.awk input-1.txt input-2.txt ...

выход

computer        succeeded       unchanged        changed failed  states run      run time
app1.domain.com 278     12      6       0       278     7.383
app2.domain.com 278     12      6       0       278     7.448
app0.domain.com 293     13      6       0       293     7.510

computer,succeeded,unchanged,changed,failed,states run,run time
app1.domain.com,278,12,6,0,278,7.383
app2.domain.com,278,12,6,0,278,7.448
app0.domain.com,293,13,6,0,293,7.510

Объяснение

BEGIN {print("computer","succeeded","unchanged","changed","failed","states run","run time");}

Печать строки заголовка CSV

FNR%8 == 1 {arr[1] = $3}

Извлечь значение arr [1] из 3-го поля в (первая строка из 8 строк)

FNR%8 == 3 {arr[2] = $2; arr[3] = extractNum($3); arr[4] = extractNum($4)}

Извлечь значения arr [2,3,4] из 2-го, 3-го, 4-го полей в (третья строка из 8 строк)

FNR%8 == 4 {arr[5] = $2;}

Извлечь значение arr [5] из 2-го поля в (4-я строка из 8 строк)

FNR%8 == 6 {arr[6] = $4;}

Извлечь значение arr [6] из 4-го поля в (6-я строка из 8 строк)

FNR%8 == 7 {arr[7] = $4;

Извлечь значение arr [7] из 4-го поля в (7-я строка из 8 строк)

print arr[1],arr[2],arr[3],arr[4],arr[5],arr[6],arr[7];}

выводить элементы массива для извлеченной переменной по завершении чтения 7-й строки из 8 строк.

function extractNum(str){match(str,/[[:digit:]]+/,m);return m[0];}

Утилита для извлечения чисел из текстового поля.

...