获取输入文件的每一行的输出。只需输出一次

时间:2012-04-04 22:02:51

标签: awk

这应该很简单但是我遇到了awk脚本流的问题。我运行以下脚本,它反复打印输出(如果我不得不猜测我会说它为输入文件的每一行打印一次)。根据要求,这里有一些虚假的输入:

[30000] (03/20 00:00:02.950):{0x2D90} Pattern1 5.0.3.57  
[30000] (03/20 00:00:03.911):{0x2D90} Pattern2 5.0.3.57  
[30000] (03/20 00:00:02.950):{0x2D90} Pattern3 5.0.3.16  
[30000] (03/20 00:00:03.911):{0x2D90} Pattern4 5.0.3.16

这是脚本:

/Pattern1/ {
    gsub(/\./,"");
    agtver=$5;
}

/Pattern2/ {
         gsub(/\./,"");
    ctrver=$5;
}

{
if (agtver ~ 50357 && ctrver ~ 50357) {
        print "Blamo!";
}
else print "No blamo. :("
}

这是我得到的输出:

[chawkins@chawkins-DT Devel]$ ./fakeawk.awk < fake.txt  
No blamo. :(  
Blamo!  
Blamo!  
Blamo!

如果模式匹配,我期望的输出是单个Blamo!,如果匹配则匹配单个No blamo. :(

问题似乎是有三个单独的{...}部分,但我需要这些部分能够处理两种模式......除非有办法压缩它。

2 个答案:

答案 0 :(得分:1)

如果您第一次看不到pattern1和pattern2,那么agtver和ctrver会保持设置状态。你必须把它们归零。

编辑添加了调试输出,您应该能够看到逻辑失败的位置。 对您的数据进行测试,感谢您添加!

/Pattern1/ { gsub(/\./,""); agtver=$5;}    
/Pattern2/ { gsub(/\./,""); ctrver=$5;}   
{
   #dbg print "\n#dbg: $5=" $5 "xx\tagtver=" agtver "xx\tctrver=" ctrver "xxx\t$0=" $0
   if (agtver ~ 50357 && ctrver ~ 50357) {
     print "Blamo!";
     agtver="" ; ctrver=""
   }
   else print "No blamo. :("
}

./fakeawk.awk < fake.txt 

<强>输出

No blamo. :(
Blamo!
No blamo. :(
No blamo. :(

我希望这会有所帮助。

答案 1 :(得分:0)

TXR:

@(gather :vars (agtver ctrver))
@  (skip :greedy) @/Pattern1/ @{agtver /5\.0\.3\.57/}
@  (skip :greedy) @/Pattern2/ @{ctrver /5\.0\.3\.57/}
@(end)
@(do (put-string "Blamo!\n"))

输出:

$ txr fake.txr fake.log
Blamo!

$ echo "junk" | txr fake.txr -
false

@(gather)指令非常适用于此。它匹配可以按任何顺序出现的材料,:vars (agtver ctrver)添加了必须为这两个变量找到绑定的约束,否则就会发生故障。

然后我们可以将我们正在寻找的两个独立条件表达为一对独立的整线模式匹配,它们绑定两个不同的变量。

逻辑可以读作“请扫描输入以收集绑定变量agtverctrver,否则将失败”。然后指定收集变量的规则,每行一个。

我们真的不需要打印Blamo!的副作用:程序的成功或失败告诉我们所有事情。