Разбор псевдо-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
(две цифры вместо трех).