Regex AWK:不使用正则表达式比较apache日期

Regex AWK:不使用正则表达式比较apache日期,regex,apache,awk,logging,Regex,Apache,Awk,Logging,我正在编写一个日志分析应用程序,希望获取两个特定日期之间的apache日志记录。假设日期的格式为:22/Dec/2009:00:19(日/月/年:小时:分钟) 目前,我正在使用正则表达式将月份名称替换为其数值,删除分隔符,因此将上述日期转换为:221220090019,使日期比较变得微不足道。。但是 在大文件的每条记录上运行正则表达式(例如,包含25万条记录的记录)成本极高。。有没有其他不涉及正则表达式替换的方法 提前谢谢 编辑:下面是进行转换/比较的函数 function dateInRang

我正在编写一个日志分析应用程序,希望获取两个特定日期之间的apache日志记录。假设日期的格式为:22/Dec/2009:00:19(日/月/年:小时:分钟)

目前,我正在使用正则表达式将月份名称替换为其数值,删除分隔符,因此将上述日期转换为:
221220090019
,使日期比较变得微不足道。。但是

在大文件的每条记录上运行正则表达式(例如,包含25万条记录的记录)成本极高。。有没有其他不涉及正则表达式替换的方法

提前谢谢

编辑:下面是进行转换/比较的函数

function dateInRange(t, from, to) {
    sub(/[[]/, "", t);
    split(t, a, "[/:]");
    match("JanFebMarAprMayJunJulAugSepOctNovDec", a[2]);
    a[2] = sprintf("%02d", (RSTART + 2) / 3);
    s = a[3] a[2] a[1] a[4] a[5];

    return s >= from && s <= to;
}
函数日期范围(t,from,to){
sub(/[]/,“”,t);
拆分(t,a,“[/:]”);
匹配(“Janfebmarapmayjunjulaugsepoctnovdec”,a[2]);
a[2]=sprintf(“%02d”,(RSTART+2)/3);
s=a[3]a[2]a[1]a[4]a[5];

return s>=from&&s我曾经遇到过一个非常慢的AWK程序的问题,该程序涉及正则表达式。当我将整个程序翻译成Perl时,它的运行速度要快得多。我想这是因为GNU AWK每次解释表达式时都编译正则表达式,而
Perl
只编译一次表达式.

我曾经遇到过一个非常慢的AWK程序的问题,这个程序涉及正则表达式。当我将整个程序翻译成Perl时,它的运行速度要快得多。我想这是因为GNU AWK每次解释表达式时都编译正则表达式,而Perl只编译表达式一次。

嗯,她e是一个概念,假设日志中的记录是按日期排序的

不要在文件中的每一行上运行regexp并检查该记录是否在所需范围内,而是执行以下操作


获取文件中的总行数。从中间读取一行并检查其日期。如果该行早于您的范围,则可以忽略该行之前的任何内容。将剩余的内容一分为二,然后再次从中间检查一行。依此类推,直到找到范围边界。

好吧,假设日志中的记录是有序的,下面是一个想法按日期

不要在文件中的每一行上运行regexp并检查该记录是否在所需范围内,而是执行以下操作

获取文件中的总行数。从中间读取一行并检查其日期。如果该行早于您的范围,则该行之前的任何内容都可以忽略。将剩余的内容一分为二,然后再次从中间检查一行。依此类推,直到找到范围边界。

根据日期对日志文件进行二进制搜索。它可以根据您的需要进行调整

它查找文件的中间部分,然后与换行符同步,读取并比较日期,重复将前一半拆分为两半的过程,直到日期匹配(大于或等于),倒带以确保之前没有相同的日期,然后读取并输出行,直到所需范围结束。速度非常快

我正在准备一个更高级的版本。最终我会完成它并发布更新的版本。

根据日期通过日志文件进行二进制搜索。它可能适合您的使用

它查找文件的中间部分,然后与换行符同步,读取并比较日期,重复将前一半拆分为两半的过程,直到日期匹配(大于或等于),倒带以确保之前没有相同的日期,然后读取并输出行,直到所需范围结束。速度非常快


我正在准备一个更高级的版本。最终我会完成它并发布更新的版本。

仅仅为了确定一个范围而剪切文件对于这样一个简单的任务来说听起来有点费力(不过二进制搜索值得考虑)

这是我修改过的函数,它显然要快得多,因为取消了正则表达式

BEGIN {
    months["Jan"] = 1
    months["Feb"] = 2
    ....
    months["Dec"] = 12
}
function dateInRange(t, from, to) {
    split(t, a, "[/:]");
    m = sprintf("%02d", months[a[2]]);
    s = a[3] m a[1] a[4] a[5];
    ok = s >= from && s <= to;
    if(!ok && seen == 1){exit;}
    return ok;
}
开始{
月份[“一月”]=1
月份[“二月”]=2
....
月份[“十二月”]=12
}
函数dateInRange(t,from,to){
拆分(t,a,“[/:]”);
m=sprintf(“%02d”,月[a[2]]);
s=a[3]ma[1]a[4]a[5];

ok=s>=从&&s仅仅为了确定一个范围而剪切文件对于这样一个简单的任务来说听起来有点费力(不过二进制搜索值得考虑)

这是我修改过的函数,它显然要快得多,因为取消了正则表达式

BEGIN {
    months["Jan"] = 1
    months["Feb"] = 2
    ....
    months["Dec"] = 12
}
function dateInRange(t, from, to) {
    split(t, a, "[/:]");
    m = sprintf("%02d", months[a[2]]);
    s = a[3] m a[1] a[4] a[5];
    ok = s >= from && s <= to;
    if(!ok && seen == 1){exit;}
    return ok;
}
开始{
月份[“一月”]=1
月份[“二月”]=2
....
月份[“十二月”]=12
}
函数dateInRange(t,from,to){
拆分(t,a,“[/:]”);
m=sprintf(“%02d”,月[a[2]]);
s=a[3]ma[1]a[4]a[5];

ok=s>=来自&&s也许除了你所要求的之外,但是当ISO 8601,即
200912220019
有这么多好处时,你到底为什么想要
2212200019
呢?我真的没有想过。这些好处与易于比较/性能有关吗?大多数记录都在同一年、同一个月、同一天和同一天(偶尔)同样的时间,所以可能是吗?在你的情况下,最重要的好处是ISO 8601的时间顺序和字母顺序变得相同。这使得年龄排序变得非常简单。也许这不是你现在需要的东西,但请帮自己一个忙,开始在所有事情上使用8601,除非你有很好的理由不这样做。其他好处也许除了你所要求的之外,你还想在ISO 8601(即
200912220019
有这么多好处时,你到底为什么想要
2212200019
呢?我真的没想过。这些好处是否与易于比较/表现有关?大多数记录都是在同一年、同一月、同一天、同一天(偶尔)同一个小时,所以可能是吗?在您的情况下,最重要的好处是ISO 8601按时间顺序和字母顺序或