Я в настоящее время запускаю awk скрипт для обработки большого файла журнала доступа (на 8.1 ГБ), и он берет навсегда для окончания. За 20 минут это записало 14 МБ (1000 + - 500) МБ, которого я ожидаю, что это запишет, и интересно, могу ли я обработать его намного быстрее так или иначе.
Вот awk сценарий:
#!/bin/bash awk '{t=$4" "$5; gsub("[\[\]\/]"," ",t); sub(":"," ",t);printf("%s,",$1);system("date -d \""t"\" +%s");}' $1
Править:
Для non-awkers сценарий читает каждую строку, получает информацию даты, изменяет его к формату утилита date
распознает и называет его для представления даты как числа секунд с 1970, наконец возвращая его как строку .csv файла, наряду с IP.
Пример ввел: 189.5.56.113 - [22/Jan/2010:05:54:55 +0100] "ДОБИРАЮТСЯ (...)"
Возвращенный вывод: 189.5.56.113,124237889
@OP, ваш скрипт медленный в основном из-за чрезмерного вызова командной даты для каждой строки в файле, а также его большой файл (в GB). Если у вас есть GAWK, используйте его внутреннюю команду mktime (), чтобы сделать дату для преобразования секунд EPOCH
awk 'BEGIN{
m=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",d,"|")
for(o=1;o<=m;o++){
date[d[o]]=sprintf("%02d",o)
}
}
{
gsub(/\[/,"",$4); gsub(":","/",$4); gsub(/\]/,"",$5)
n=split($4, DATE,"/")
day=DATE[1]
mth=DATE[2]
year=DATE[3]
hr=DATE[4]
min=DATE[5]
sec=DATE[6]
MKTIME= mktime(year" "date[mth]" "day" "hr" "min" "sec)
print $1,MKTIME
}' file
$ more file
189.5.56.113 - - [22/Jan/2010:05:54:55 +0100] "GET (...)"
$ ./shell.sh
189.5.56.113 1264110895
Если вам действительно действительно нужно, чтобы это было быстрее, вы можете сделать то, что сделал Отказ Я переписал анализатор файлов журнала Apache, используя Ragel. Ragel позволяет смешивать регулярные выражения с помощью C-кода. Регулярные выражения преобразуются в очень эффективный C-код, а затем скомпилированы. К сожалению, это требует, чтобы вы были очень удобны , написание кода в C. У меня больше нет этого анализатора. Это обработано 1 ГБ журналов доступа APACHACE в течение 1 или 2 секунд.
У вас может быть ограниченный успех, удаляя ненужные Printfs от вашего заявления awk и замена их чем-то более простым.
Если вы используете GAWK
, вы можете помассировать свою дату и время в формате, который MKTime
(A Gawk
Функция ) понимает. Он даст вам тот же временные метки, которые вы используете сейчас и сохраняете накладные расходы повторных системы ()
вызовов.
Этот маленький сценарий Python обрабатывает копии копий ~ 400 МБ ваша примера строки примерно в 3 минутах на моем машине, производит ~ 200 МБ выхода (имейте в виду, что ваша линейка образца была довольно короткими, так что это Handicap):
import time
src = open('x.log', 'r')
dest = open('x.csv', 'w')
for line in src:
ip = line[:line.index(' ')]
date = line[line.index('[') + 1:line.index(']') - 6]
t = time.mktime(time.strptime(date, '%d/%b/%Y:%X'))
dest.write(ip)
dest.write(',')
dest.write(str(int(t)))
dest.write('\n')
src.close()
dest.close()
Незначительная проблема состоит в том, что она не обрабатывает часовые появления (STRPTIME () проблемы), но вы можете либо жесткокодировать, либо добавить немного дополнительных, чтобы позаботиться об этом.
Но если честно, что-то простое, как это должно быть так же легко переписать в C.