awk Arrays

So I'm back once again beating my head off a wall trying to figure out how to get this to work.

My end goal is to take input such as what's below, which will be capture in real time with a tail -f from a file or piped output from another command:

[2013/01/20 19:19:19] mod=syn|cli=192.168.1.102/56231|srv=192.168.1.110/443|subj=cli|os=Windows 7 or 8|dist=0|params=none|raw_sig=4:128+0:0:1460:8192,0:mss,nop,nop,sok:df,id+:0
[2013/01/20 19:19:19] mod=mtu|cli=192.168.1.102/56231|srv=192.168.1.110/443|subj=cli|link=Ethernet or modem|raw_mtu=1500
[2013/01/20 19:19:19] mod=syn|cli=192.168.1.102/56232|srv=192.168.1.110/443|subj=cli|os=Windows 7 or 8|dist=0|params=none|raw_sig=4:128+0:0:1460:8192,0:mss,nop,nop,sok:df,id+:0

And output it into something that looks like this:

Subject=cli
Server=192.168.1.110
Client=192.168.1.102
OS=Windows 7 or 8

etc. etc. for each line that it finds.

Below is what I've come up with so far, and it's not working properly.

awk -F"|" '{ { COUNT=1 }
        for(i=1;i<=NF;i++)
                {
                        if ($i ~ /cli=/)
                                {cli[$COUNT]=$i;gsub (/cli=/,"",cli[$COUNT]);}
                        if ($i ~ /srv=/)
                                {srv[$COUNT]=$i;gsub (/srv=/,"",srv[$COUNT]);}
                        if ($i ~ /subj=/)
                                {subj[$COUNT]=$i;gsub (/subj=/,"",subj[$COUNT]);}
                        if ($i ~ /os=/)
                                {os[$COUNT]=$i;gsub (/os=/,"",os[$COUNT]);}
                        { COUNT++ }
                }
        }
        {
        for(i=1;i<=COUNT;i++)
                {
                        {printf "Subject = %s\nServer = %s\nClient= %s\nOS= %s\n", subj[$i], srv[$i], cli[$i], os[$i];}
                        { i++ }
                }
        }'

I am trying to load the variables into an array as it runs through each pass so that I can print them out in the proper order... It doesn't seem to be working for me at all though.

If anyone could help, it would be appreciated.

Thanks,
-Shadow

awk -F\| '{
 for(i=1;i<=NF;i++) {
  if($i ~ /subj=/) { sb=$i; gsub(/.*=/,"",sb); }
  if($i ~ /srv=/) { sr=$i; gsub(/.*=|\/.*/,"",sr); }
  if($i ~ /cli=/) { cl=$i; gsub(/.*=|\/.*/,"",cl); }
  if($i ~/os=/) { os=$i; gsub(/.*=/,"",os); }
  if(i==NF) { printf "Subject= %s\nServer= %s\nClient= %s\nOS= %s\n",sb,sr,cl,os; sb=sr=cl=os=""; }
 }
}' infile
1 Like

The printf statement can be moved out of the for loop, then the if statement is not required..

Thank you Bipinajith!

So I'm going to explain what I think is happening, and someone can correct me if I'm wrong so I can learn here.

Once it reads through all the variables and stores what it finds, it gets to the if(i==NF) and that tells it that it's done and to print out what it has stored.

Then it sets all of the variables back to empty so they can be used again the next run without returning old information.

One question on this: /.*=|\/.*/

I'm guessing that .*= means pick up anything before the equal sign and remove it.

What does the other side of that do? What does the |\/.* do?

I know that the \ is an excape character, so does it find anything after a / and remove it?

Yes, you are right. \/.* removes everything after / for server & client IP addresses.

/ is a meta-character, hence it should be escaped.

1 Like

Thank you sir! Appreciate your quick responses and helpfulness.