Getting output for every line of input file. Only need output once

Go To StackoverFlow.com

1

This should be pretty simple but I'm having an issue with the flow of an awk script. I run the following script and it prints the output over and over again (if I had to guess I would say that it's printing once for every line of the input file). As requested, here is some fake input:

[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

Here is the script:

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

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

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

And here is the output that I'm getting:

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

The output that I expect is a single Blamo! if the patterns match and a single No blamo. :( if it doens't match.

The problem seems to be that there are three separate { ... } sections, but I need these to be able to process two patterns... unless there is a way to condense this.

2012-04-04 22:02
by satori7
I see this (plus a whole lot more): Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! Blamo! The logic is working as expected, it's just outputting way too much - satori7 2012-04-04 22:35
You don't actually say what exactly you want the script to do. It is doing what you are telling it to, even if that's not what you meant. Perhaps you want to zero out agt and ctr versions, other than that, what do you actually want the script to do? What do you want the output for this sample data to be - Kevin 2012-04-05 02:19


1

If you never see pattern1 and pattern2 after the first time, then agtver and ctrver remain set. You have to zero them out again.

edit added debug output, you should be able to see where the logic is failing. Tested with your data, thanks for adding that!

/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 

output

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

I hope this helps.

2012-04-04 22:38
by shellter
Still no good. In fact that made the logic not work which doesn't really make sense. So here's the deal. I am parsing a log file looking for two version numbers. Upon matching those version numbers it will print a human friendly version like "Version 5 Service Pack 3". Unfortunately for confidentiality reasons I cannot post specifics - satori7 2012-04-04 23:08
I made a small file sample with 'pattern1', pattern2, etc as lines with the 50357 in the right place. Can't you do that too? As repeated several times now, please edit you post to include sample (fake) data and expected output. If it works for the sample, it should work once you fix all your patterns. Good luck - shellter 2012-04-04 23:10
Thanks. That is why the gsub is there. It strips out the "." so that it becomes "50357" - satori7 2012-04-05 00:31
Doah... about gsub(). OK, is this the output you expect? If not turn on the #dbg line to see variable status as each line is read, and adjust your logic as needed. Your revised version missed the critical agtver="" ; ctrver="". Good luck and will check back in 1/2 hr or so - shellter 2012-04-05 02:30
Hm, just noticed the tile of your question says 'Only need output once', does that mean you expect only 1 line of output? The Blamo! ? Then do you just need to remove the else print "No blamo" or if this is wrong, the please update your question with expected output. Good luck - shellter 2012-04-05 02:34


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"))

Output:

$ txr fake.txr fake.log
Blamo!

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

The @(gather) directive is perfect for this. It matches material that can appear in any order, and :vars (agtver ctrver) adds the constraint that bindings must be found for both of these variables, or else a failure occurs.

We can then express the two indepedent conditions we are looking for as a pair of independent whole-line pattern matches which bind two different variables.

The logic may be read as "please scan the input to gather bindings variables agtver and ctrver or else fail". And then the rules for gathering the variables are specified, one per line.

We don't really need the side effect of printing Blamo!: the successful or failed termination of the program tells us everything.

2012-04-05 19:07
by Kaz
This is very cool and looks like it would do the job, but this has to be done with awk (it is part of a larger awk script). If it were my choice I would use Perl, but that's just me. : - satori7 2012-04-08 21:37
Ads