Разбор псевдо-HTML/XML файлов журнала во фрейм данных (Symantec Altiris) [R]

Меня попросили помочь разобрать некоторые файлы журналов для приложения Symantec (Altiris), и они были доставлены мне в формате псевдо-HTML/XML. Мне удалось использовать readLines() а также grepl() чтобы получить логи в приличном символьном векторном формате и очистить ненужные файлы, но не могу поместить их во фрейм данных.

На данный момент запись выглядит примерно так (поскольку я не могу опубликовать реальные данные), все в символьном векторе со структурой chr[1:312]:

[310] "<severity='4', hostname='computername125', source='PackageDownload', module='herpderp.dll', process='masterP.exe', pid='234' >"

Мне не повезло с синтаксическим анализом XML, и он для меня больше похож на HTML, и когда я попробовал htmlTreeParse(x) Я только что закончил с массивной пирамидой тегов.

1 ответ

Решение

Если вы работаете с псевдо-XML, вероятно, лучше всего определить правила синтаксического анализа самостоятельно. мне нравится stringr а также dplyr за такие вещи, как это.

Вот двухэлементный вектор (вместо 312 в вашем случае):

vec <- c(
  "<severity='4', hostname='computername125', source='PackageDownload', module='herpderp.dll', process='masterP.exe', pid='234' >",
  "<severity='5', hostname='computername126', source='PackageDownload', module='herpderp.dll', process='masterP.exe', pid='235' >"
)

Преобразуйте это в data.frame объект:

df <- data.frame(vec, stringsAsFactors = FALSE)

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

require(stringr)
require(dplyr)

df %>%
  mutate(
    severityStr = str_locate(vec, "severity")[, "start"],
    hostnameStr = str_locate(vec, "hostname")[, "start"],
    sourceStr = str_locate(vec, "source")[, "start"],
    moduleStr = str_locate(vec, "module")[, "start"],
    processStr = str_locate(vec, "process")[, "start"],
    pidStr = str_locate(vec, "pid")[, "start"],
    endStr = str_locate(vec, ">")[, "start"],
    severity = substr(vec, severityStr + 10, hostnameStr - 4),
    hostname = substr(vec, hostnameStr + 10, sourceStr - 4),
    source = substr(vec, sourceStr + 8, moduleStr - 4),
    module = substr(vec, moduleStr + 8, processStr - 4),
    process = substr(vec, processStr + 9, pidStr - 4),
    pid = substr(vec, pidStr + 5, endStr - 3)) %>%
  select(severity, hostname, source, module, process, pid)

Вот результирующий фрейм данных:

  severity        hostname          source       module     process pid
1        4 computername125 PackageDownload herpderp.dll masterP.exe 234
2        5 computername126 PackageDownload herpderp.dll masterP.exe 235

Это решение достаточно надежно для обработки строковых входов различной длины. Например, это будет читать pid правильно, даже если это 95 (две цифры вместо трех).

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