awk 中的性能比较?

Performant comparisons in awk?

我有一个 python 脚本,它运行一些日志,我认为在部署它之前针对其他一些方法做一些基准测试是有益的。在查看 awk 时,我希望将开销降至最低,从而在击败稍微优化的 python 变体时获得 'fair' 的震撼。

我的日志条目如下所示:

--------
SomeField=SomeValue
OptionallyAppearingField=WhoKnowsWhat
AnotherField=AnotherValue
ExtraStuff=OneBonusKey=1,SecondBonusKey=2,ThirdBonusKey=3,...
--------

当我们的 ThirdBonusKey 之一存在并且具有特定值(实际上只是数字 1)时,我很想获得 AnotherField 的值。

这里的'stupid'方法是将我们的RS设置为'--------',然后将正则表达式应用于[=18=]两次,首先查看是否ThirdBonusKey=1在记录中,然后提取AnotherField=(desired_value)

但这似乎是一个不公平的比较,因为它只是针对问题抛出一个正则表达式(两次!)。如果没有保证字段的顺序来利用 awk 的出色 FS 技能,这里是否有更快或更合适的方法?答案有可能只是 "this is not a job for awk",我想这也没关系。

Cyrus 友善地指出我上面给出的代码草图在技术上不是代码,但他在技术上是正确的,所以这是一个相当愚蠢的实现:

awk 'BEGIN{RS="--------"} { if ([=11=] ~ /ThirdBonusKey=1/) { for(i=1;i<NF;i++) {if ($i ~ "AnotherField=") { print $i }}}}'

给定输入

--------
SomeField=SomeValue
OptionallyAppearingField=WhoKnowsWhat
AnotherField=DesiredValue1
ExtraStuff=OneBonusKey=1,SecondBonusKey=2,ThirdBonusKey=1,...
--------
SomeField=SomeValue
OptionallyAppearingField=WhoKnowsWhat
AnotherField=DesiredValue2
ExtraStuff=OneBonusKey=1,SecondBonusKey=2,ThirdBonusKey=0,...
--------
SomeField=
ExtraStuff=
--------

我们期望输出

AnotherField=DesiredValue1

我期望的最有效:

$ awk '/^AnotherField=/{val=[=10=]; next} /[=,]ThirdBonusKey=1(,|$)/{print val}' file
AnotherField=DesiredValue1

但更强大、更容易增强以执行您以后想要的任何其他操作:

$ cat tst.awk
BEGIN { FS="[,=[:space:]]"; OFS="=" }
/^-+$/ {
    if ( f["ExtraStuff_ThirdBonusKey"] == 1 ) {
        print "AnotherField", f["AnotherField"]
    }
    delete f
    next
}
{
    if (  == "ExtraStuff" ) {
        pfx = 
        sub(/[^=]+=/,"")
        f[pfx] = [=11=]
        pfx = pfx "_"
    }
    else {
        pfx = ""
    }
    for (i=1; i<NF; i+=2) {
        f[pfx $i] = $(i+1)
    }
}

$ awk -f tst.awk file
AnotherField=DesiredValue1

第二个脚本首先将所有值存储在一个数组中 f[] 因此您可以通过名称访问这些值,该数组的内容如下所示:

$ cat tst.awk
BEGIN { FS="[,=[:space:]]"; OFS="=" }
/^-+$/ {
    for (i in f) printf "> f[%s]=%s\n", i, f[i]
    if ( f["ExtraStuff_ThirdBonusKey"] == 1 ) {
        print "AnotherField", f["AnotherField"]
    }
    print "----"
    delete f
    next
}
{
    if (  == "ExtraStuff" ) {
        pfx = 
        sub(/[^=]+=/,"")
        f[pfx] = [=12=]
        pfx = pfx "_"
    }
    else {
        pfx = ""
    }
    for (i=1; i<NF; i+=2) {
        f[pfx $i] = $(i+1)
    }
}

.

$ awk -f tst.awk file
----
> f[OptionallyAppearingField]=WhoKnowsWhat
> f[AnotherField]=DesiredValue1
> f[ExtraStuff_SecondBonusKey]=2
> f[ExtraStuff_ThirdBonusKey]=1
> f[ExtraStuff_OneBonusKey]=1
> f[SomeField]=SomeValue
> f[ExtraStuff]=OneBonusKey=1,SecondBonusKey=2,ThirdBonusKey=1,...
AnotherField=DesiredValue1
----
> f[OptionallyAppearingField]=WhoKnowsWhat
> f[AnotherField]=DesiredValue2
> f[ExtraStuff_SecondBonusKey]=2
> f[ExtraStuff_ThirdBonusKey]=0
> f[ExtraStuff_OneBonusKey]=1
> f[SomeField]=SomeValue
> f[ExtraStuff]=OneBonusKey=1,SecondBonusKey=2,ThirdBonusKey=0,...
----
> f[SomeField]=
> f[ExtraStuff]=
----

鉴于您可以创建任何条件and/or以任何输入或输出顺序打印您想要的任何字段组合。