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以任何输入或输出顺序打印您想要的任何字段组合。
我有一个 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以任何输入或输出顺序打印您想要的任何字段组合。