Использование awk для разбора и преобразования следующего журнала - PullRequest
0 голосов
/ 08 июля 2019

У меня есть такой журнал:

DEBUG: Worker thread (#12) initialized
DEBUG: Worker thread (#19) initialized
DEBUG: Worker thread (#9) initialized
DEBUG: Worker thread (#15) initialized
DEBUG: Worker thread (#3) initialized
DEBUG: Worker thread (#17) initialized
DEBUG: Worker thread (#14) initialized
DEBUG: Worker thread (#16) initialized
Threads started!

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
...

Я хочу проанализировать этот файл журнала и получить все следующие строки:

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
....

Затем я хочу преобразовать эти строки вследующий формат для построения графиков:

5,35265.85
10,35965.67
...

Вот мой код awk:

#!/usr/bin/env bash
awk '
BEGIN {
printf "#time,tps\n";
}
/^\[\ [0-9]{1,4}[s]?\ \]/ { # regex for [ 1050s ]
printf "%s,%s\n", substr($2,1, length($2)-1), $7
}
' "$@"

В этом решении мне не нравится то, что мне не нравится: я должен вручную подсчитать индекс токеновгенерируется awk.Я предпочитаю лучшее решение, такое как: «первый токен после строки« tps »».Таким образом, он будет более общим и простым при разборе.

Мой вопрос: могу ли я сделать это с помощью awk.Или есть ли лучшие решения для решения моей ситуации?

Ответы [ 3 ]

2 голосов
/ 08 июля 2019

Вот один из способов сделать это.Предполагая, что ваш файл журнала называется data.txt.Вы можете запустить следующее

cat data.txt | grep -wE "5s|10s" | awk '{print substr($(NF-16), 1, length($(NF-16))-1) "," $(NF-13) "," $(NF-11) "," $(NF-9)}' 

Объяснение

  1. cat <filename> выводит содержимое файла на стандартный вывод
  2. grep -wE <exp> фильтрует вывод из котаи выбирает строки, содержащие выражение, которое в нашем случае 5s or 10s.-w гарантирует, что будут выбраны только те строки, которые соответствуют целому слову, или 5s без -w также выберет 15s, 20s .. и т. д.,

При этом будут выбраны следующие строки, на которыхawk выполняется

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
Используя awk, мы можем использовать NF, чтобы узнать количество полей в каждой строке awk '{print NF}', то есть 18

Извлечь соответствующее содержимое, которое находится в NF-16, NF-13, NF-11 и NF-9 й позиции.т.е. 2, 5, 7 и 9 позиции соответственно.Однако, 2-я позиция - 5s|10s и т. Д., И вы хотите удалить хвост s, который можно сделать с помощью substr($2, 1, length($2)-1), т. Е. От 1-го символа до длины 5 с / 10 с, т. Е. 2/3 соответственно, и удалитьпоследний символ (ы), используя -1.

Ваша последняя команда

awk '{print substr($(NF-16), 1, length($(NF-16))-1) "," $(NF-13) "," $(NF-11) "," $(NF-9)}'

и может быть заменена на

awk '{print substr($2, 1, length($2)-1)","$5","$7","$9}'

Собрав все вместе, вы получите

cat data.txt | grep -wE "5s|10s" | awk '{print substr($2, 1, length($2)-1)","$5","$7","$9}'
1 голос
/ 08 июля 2019

Это то, что вы пытаетесь сделать?

$ awk -v OFS=',' '/^\[/{print $2+0, $5, $7, $9}' file
5,20,35265.85,35265.85
10,20,35965.67,35965.67
15,20,35233.82,35233.82
20,20,35239.05,35239.25
25,20,37188.61,37188.41
30,20,36622.32,36622.32
35,20,36538.27,36538.27

или, может быть, это, если вы хотите заголовки:

awk -F'[ :]+' -v OFS=',' '/^\[/{ if (!doneHdr++) print "time", $4, $6, $8; print $2+0, $5, $7, $9}' file
time,thds,tps,qps
5,20,35265.85,35265.85
10,20,35965.67,35965.67
15,20,35233.82,35233.82
20,20,35239.05,35239.25
25,20,37188.61,37188.41
30,20,36622.32,36622.32
35,20,36538.27,36538.27

или это:

$ awk -F'[ :]+' -v OFS=',' -v tgts='time thds tps qps' '
    BEGIN {
        numTags = split(tgts,tags)
        for (tagNr=1; tagNr<=numTags; tagNr++) {
            printf "%s%s", tags[tagNr], (tagNr<numTags ? OFS : ORS)
        }
    }
    /^\[/ {
        for (i=1; i<=NF; i++) {
            f[$i] = $(i+1)
            sub(/[^0-9]+$/,"",f[$i])
        }
        f["time"] = f["["]

        for (tagNr=1; tagNr<=numTags; tagNr++) {
            printf "%s%s", f[tags[tagNr]], (tagNr<numTags ? OFS : ORS)
        }
    }
' file
time,thds,tps,qps
5,20,35265.85,35265.85
10,20,35965.67,35965.67
15,20,35233.82,35233.82
20,20,35239.05,35239.25
25,20,37188.61,37188.41
30,20,36622.32,36622.32
35,20,36538.27,36538.27

Я запустил выше, используя ваш исходный пример ввода:

$ cat file
DEBUG: Worker thread (#12) initialized
DEBUG: Worker thread (#19) initialized
DEBUG: Worker thread (#9) initialized
DEBUG: Worker thread (#15) initialized
DEBUG: Worker thread (#3) initialized
DEBUG: Worker thread (#17) initialized
DEBUG: Worker thread (#14) initialized
DEBUG: Worker thread (#16) initialized
Threads started!

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
[ 15s ] thds: 20 tps: 35233.82 qps: 35233.82 (r/w/o: 0.00/35233.82/0.00) lat (ms,99%): 2.26 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 20 tps: 35239.05 qps: 35239.25 (r/w/o: 0.00/35239.25/0.00) lat (ms,99%): 2.11 err/s: 0.00 reconn/s: 0.00
[ 25s ] thds: 20 tps: 37188.61 qps: 37188.41 (r/w/o: 0.00/37188.41/0.00) lat (ms,99%): 1.86 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 20 tps: 36622.32 qps: 36622.32 (r/w/o: 0.00/36622.32/0.00) lat (ms,99%): 1.96 err/s: 0.00 reconn/s: 0.00
[ 35s ] thds: 20 tps: 36538.27 qps: 36538.27 (r/w/o: 0.00/36538.27/0.00) lat (ms,99%): 2.00 err/s: 0.00 reconn/s: 0.00
1 голос
/ 08 июля 2019

С tr и awk:

tr -cd '0-9 .\n' <file | awk 'NF>1 && NF=4' OFS=","

Удалить все символы из файла, кроме цифр 0-9, пробела, точки и новой строки с tr и вывести оставшиеся символы в команду awk.Если строка содержит более одного столбца (NF>1), уменьшите количество столбцов до четырех (NF=4).

Вывод:

5,20,35265.85,35265.85
10,20,35965.67,35965.67
15,20,35233.82,35233.82
20,20,35239.05,35239.25
25,20,37188.61,37188.41
30,20,36622.32,36622.32
35,20,36538.27,36538.27

См.: 8 Мощные встроенные переменные Awk - FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

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