mr.*_*r.b 16 bash text logfiles
我有一个Apache access.log文件,大小约为35GB.通过它不再是一种选择,不需要等待很多.
我希望通过使用日期作为拆分标准将其拆分为许多小文件.
日期格式[15/Oct/2011:12:02:02 +0000].任何想法我怎么能只使用bash脚本,标准文本操作程序(grep,awk,sed和喜欢),管道和重定向?
输入文件名是access.log.我希望输出文件具有这样的格式access.apache.15_Oct_2011.log(这可以解决问题,但在排序时不太好.)
The*_*ith 17
一种方式使用awk:
awk 'BEGIN {
split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ", months, " ")
for (a = 1; a <= 12; a++)
m[months[a]] = a
}
{
split($4,array,"[:/]");
year = array[3]
month = sprintf("%02d", m[array[2]])
print > FILENAME"-"year"_"month".txt"
}' incendiary.ws-2009
Run Code Online (Sandbox Code Playgroud)
这将输出如下文件:
incendiary.ws-2010-2010_04.txt
incendiary.ws-2010-2010_05.txt
incendiary.ws-2010-2010_06.txt
incendiary.ws-2010-2010_07.txt
Run Code Online (Sandbox Code Playgroud)
对于一个150 MB的日志文件,chepner的答案在3.4 GHz 8 Core Xeon E31270上耗时70秒,而这种方法耗时5秒.
原创灵感:" 如何按月拆分现有的apache日志文件? "
che*_*ner 10
纯粹的bash,一次通过访问日志:
while read; do
[[ $REPLY =~ \[(..)/(...)/(....): ]]
d=${BASH_REMATCH[1]}
m=${BASH_REMATCH[2]}
y=${BASH_REMATCH[3]}
#printf -v fname "access.apache.%s_%s_%s.log" ${BASH_REMATCH[@]:1:3}
printf -v fname "access.apache.%s_%s_%s.log" $y $m $d
echo "$REPLY" >> $fname
done < access.log
Run Code Online (Sandbox Code Playgroud)
这是一个awk输出可按词法排序的日志文件的版本。
一些效率增强:所有操作一次完成,仅fname在与以前不同时生成,fname切换到新文件时关闭(否则可能会用完文件描述符)。
awk -F"[]/:[]" '
BEGIN {
m2n["Jan"] = 1; m2n["Feb"] = 2; m2n["Mar"] = 3; m2n["Apr"] = 4;
m2n["May"] = 5; m2n["Jun"] = 6; m2n["Jul"] = 7; m2n["Aug"] = 8;
m2n["Sep"] = 9; m2n["Oct"] = 10; m2n["Nov"] = 11; m2n["Dec"] = 12;
}
{
if($4 != pyear || $3 != pmonth || $2 != pday) {
pyear = $4
pmonth = $3
pday = $2
if(fname != "")
close(fname)
fname = sprintf("access_%04d_%02d_%02d.log", $4, m2n[$3], $2)
}
print > fname
}' access-log
Run Code Online (Sandbox Code Playgroud)