Анализ журнала с использованием awk и sed - PullRequest
1 голос
/ 26 мая 2020

У меня есть

2019-11-14T09:42:14.150Z  INFO ActivityEventRecovery-1 ActivityCacheManager - - [nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"] Handling activity 0082bc26-70a6-433e-a470-
2019-11-14T09:43:08.097Z  INFO L2HostConfigTaskExecutor2 TransportNodeAsyncServiceImpl - FABRIC [nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"] Calling uplinkTeamingChangeListener.onTransportNodeUpdated on TN 72f73c66-da37-11e9-8d68-005056bce6a5 revision 5
2019-11-14T09:43:08.104Z  INFO L2HostConfigTaskExecutor2 Publisher - ROUTING [nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"] Refresh mac address of Logical router port connected with VLAN LS for logical router LogicalRouter/f672164b-40cf-461f-9c8d-66fe1e7f8c19
2019-11-14T09:43:08.105Z  INFO L2HostConfigTaskExecutor2 GlobalActivityRepository - - [nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"] Submitted activity 73e7a942-73d2-4967-85fa-7d9d6cc6042b in QUEUED state with dependency null exclusivity true and requestId null and time taken by dao.create is 1 ms

такие журналы, в которых я хочу преобразовать их в объект json. До сих пор я использовал регулярное выражение python и помещал его в словарь.

    currentDict = {
                               "@timestamp" : regexp.group(1),
                               "Severity" : regexp.group(2),
                               "Thread" : regexp.group(3),
                               "Class" : regexp.group(4),
                               "Message-id" : regexp.group(5),
                               "Component" : regexp.group(6),
                               "Message" : regexp.group(7),
                               "id's" : re.findall(x[1], regexp.group(7))
                        }

, но в этом случае он очень медленный, т.е. занимает 5-10 минут для файла 200 МБ.

Python regex Я использовал - (\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ)\s+(INFO|WARN|DEBUG|ERROR|FATAL|TRACE)\s+(.*?)\s+(.*?)\s+\-\s+(.*?)\s+(?:(\[?.*?\])?)\s(.*)

Ожидаемый результат -

{"@timestamp" : "2019-11-14T09:42:14.150Z", "Sevirity" : "INFO", "Thread" : "ActivityEventRecovery-1", "Class" : "ActivityCacheManager - -", "Component" : "[nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"]", "Message" : "Handling activity 0082bc26-70a6-433e-a470-"}
{"@timestamp" : "2019-11-14T09:43:08.097Z", "Sevirity" : "INFO", "Thread" : "L2HostConfigTaskExecutor2", "Class" : "TransportNodeAsyncServiceImpl - FABRIC", "Component" : "[nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"]", "Message" : "Calling uplinkTeamingChangeListener.onTransportNodeUpdated on TN 72f73c66-da37-11e9-8d68-005056bce6a5 revision 5}"}
{"@timestamp" : "2019-11-14T09:43:08.104Z", "Sevirity" : "INFO", Thread : "L2HostConfigTaskExecutor2", "Class" : "Publisher - ROUTING", "Component" : "[nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"]", Message : "Refresh mac address of Logical router port connected with VLAN LS for logical router LogicalRouter/f672164b-40cf-461f-9c8d-66fe1e7f8c19}"}
{"@timestamp" : "2019-11-14T09:43:08.105Z", "Sevirity" : "INFO", "Thread" :  "L2HostConfigTaskExecutor2", "Class" :   "GlobalActivityRepository", "Component" : "[nsx@6876 comp="nsx-manager" level="INFO" subcomp="manager"]", "Messages" : "Submitted activity 73e7a942-73d2-4967-85fa-7d9d6cc6042b in QUEUED state with dependency null exclusivity true and requestId null and time taken by dao.create is 1 ms"}}

На inte rnet я обнаружил, что с помощью awk и sed это можно сделать быстрее. Я мало что знаю об этом. Как выполнить синтаксический анализ с использованием awk и sed.

Пожалуйста, помогите!

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

Этот сценарий sed должен выполнять очень быструю работу:

sed -E 's/^([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+\s-\s[^ ]+)\s+(\[.*\])\s+(.*)$/{"@timestamp" : "\1", "Severity" : "\2", "Thread" : "\3", "Class" : "\4", "Component" : "\5", "Message" "\6"}/' inputdata.dat

Объяснение:

  • sed 's/^<regular-expression>$/<output-string>/' манипулирует / заменяет каждый ^<input-line>$, который соответствует регулярному выражению. При этом ^ означает начало и $ конец строки .
  • -E: означает использовать расширенные регулярные выражения . Расширенные регулярные выражения теперь включены в POSIX. На странице руководства grep вы можете найти:

    Basi c против расширенных регулярных выражений:

    В basi c регулярных выражениях метасимволы? , +, {, |, (, и) теряют свое особое значение; вместо этого используйте версии с обратной косой чертой \ ?, \ +, \ {, \ |, \ (и \).

  • (...)...(...)...(...)...: содержимое внутри (...) является - в этом скрипте - описание для соответствия первому, второму, третьему ... шестому полю данных. В общем, это инструмент для разделения всего регулярного выражения на разные единицы, на которые вы можете ссылаться в выходной строке через \1, \2 .... Таким образом, вы можете ограничить манипуляции с текстом определенными контекстами. В этом случае сами поля данных остаются неизменными, изменяется только контекст.

  • [^ ]+: внутри [...] описывается класс символов [A-Za-z0-9] означает ровно один символ алфавита или цифры , [0-9]+ означает хотя бы один di git, [ ] означает один пробел , [^0-9 ] означает ровно один символ - все, что угодно, кроме di git и кроме пустого , поэтому здесь [^ ]+ означает по крайней мере один символ - что угодно, кроме пустого -> правильный шаблон регулярного выражения для содержимого первые три поля данных
  • ([^ ]+\s-\s[^ ]+): четвертое поле данных «Класс» представляет собой составное поле данных, два компонента и разделитель ' - ' (1-й - 2-й), за пределами классов символов ([..] ) используйте \s вместо ' '
  • (\[.*\]): пятое поле данных «Компонент» также является полем составных данных, но заключено в квадратные скобки [ и ]. Чтобы соответствовать самому символу скобки (а не классу char, заключающему эти символы в скобки), вы должны использовать символ скобки [ или ], которому предшествует backsla sh \. . - это подстановочный знак, поэтому .* в \[.*\] означает все, что находится в скобках
  • \s+: хотя бы один пробел или табулятор (между полями данных)
  • поэтому шестое поле данных - сообщение гибкой длины - может быть сопоставлено как (.*), что означает остаток после ] и следующий за ним пробел до конца строки
  • \1 ... \6 (в правой части): ссылки в выходной строке на соответствующую группу выражений (в данном случае поля данных) внутри регулярного выражения.
  • inputdata.dat: замените это на имя вашего файла данных

Чтобы получить исполняемый сценарий оболочки, сохраните его как файл:

#! /bin/sh
sed -E 's/^([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+\s-\s[^ ]+)\s+(\[.*\])\s+(.*)$/{"@timestamp" : "\1", "Severity" : "\2", "Thread" : "\3", "Class" : "\4", "Component" : "\5", "Message" "\6"}/' "$1" >"$2"

После этого выполните команду chmod +x <your-scriptname> сделать скрипт исполняемым. Затем его можно запустить как ./<your-scriptname> <input-file> <wanted-output-file-name>.

Внимание:

  • НЕ используйте одно и то же имя файла для входного и выходного файла
  • Если файл с выходом имя файла уже существует, оно будет отменено.
0 голосов
/ 26 мая 2020
# For timestamp
cut -d " " -f 1 in > temp
sed -i -e 's/^/{"@timestamp" : "/' temp
awk 'NF{print $0 "\", "}' temp > a

# For Severity ...

# For Thread ...

# For Class
cut -d " " -f 5,6,7 in > temp
sed -i -e 's/^/"Class" : "/' temp
awk 'NF{print $0 "\", "}' temp > d

# For Component
grep -o -P '(?<=\[).*(?=\])' in > temp
sed -i -e 's/^/"Component" : \["/' temp
awk 'NF{print $0 "\"], "}' temp > e

# For Message ...

# Merge all files line by line
paste -d " " a b c d e f

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

Я оставил разделы «Серьезность», «Тема» и «Сообщение», поскольку они такие же, как и другие. Сценарий довольно прост, но вы не поймете его, не зная, как использовать сами инструменты, поскольку вы сказали, что не знаете о них.

...