3 Replies - 2330 Views - Last Post: 10 March 2010 - 05:02 AM

#1 stsmiley   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 18-November 09

stuck on creating hash table in perl

Posted 08 March 2010 - 05:54 PM

ok so i'm very new to perl and i've been going through these assignments a buddy gave me from his class so I can learn my way around perl a little and I got kinda stuck and needed a little help. I have this file, a log file from a firewall that watched different ips and the ports they scanned, now im trying to output that into a hash table to show the different ips and the ports each one tried to scan. Here is what I have so far, first i need to make meaningful named variables out of $1 and $2 which im not quite sure how to do then put it all into a hash table for output.

open ASSIGNMENT, "Log.log" or die "Can't open Log.log", $!;
$count = 0;

while ($record = <ASSIGNMENT>)
{
if ($record =~ /INext-DROP/){
	$count++;}
	$record =~ /(SRC=[0-9\.]* ).*(DPT=[0-9\.]* )/;
	print $1, $2;}
close ASSIGNMENT;


any help at all can be helpful, im gonna attach the assignment that my buddy has me trying so that might help give you some perspective.

Attached File(s)

  • Attached File  perl.doc (30K)
    Number of downloads: 228


Is This A Good Question/Topic? 0
  • +

Replies To: stuck on creating hash table in perl

#2 dsherohman   User is offline

  • Perl Parson
  • member icon

Reputation: 227
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: stuck on creating hash table in perl

Posted 09 March 2010 - 05:01 AM

View Poststsmiley, on 09 March 2010 - 12:54 AM, said:

Here is what I have so far, first i need to make meaningful named variables out of $1 and $2 which im not quite sure how to do then put it all into a hash table for output.


Generally, they're just called "hashes" in Perl and they basically just function like associative arrays if you're familiar with those from other languages. To associate a value with a key in a hash, the syntax is just "$hash{$key} = $value". To refer to the hash as a whole, use "%hash".

Now, on to the code!

Quote

open ASSIGNMENT, "Log.log" or die "Can't open Log.log", $!;


This is a very old and somewhat insecure style for opening a file. The preferred style today is to use the three-argument form of open and to use a "lexical filehandle" (which basically just means putting the handle into a regular variable instead of using a global for it).

What that would look like is:
open my $assignment, '<', 'Log.log' or die "Can't open Log.log", $!;
With this change, you also need to change later references to the filehandle from "ASSIGNMENT" to "$assignment", of course.

Quote

$count = 0;


Especially when you're learning Perl, you always want to start every program with "use strict; use warnings;", but strict will flag this line as an error because you're trying to use the global $count and it doesn't know about any such global variable existing. But you don't really want $count to be global anyhow, so fix this error by declaring is as a lexical variable:
my $count = 0;


Quote

while ($record = <ASSIGNMENT>)
{
if ($record =~ /INext-DROP/){
	$count++;}
	$record =~ /(SRC=[0-9\.]* ).*(DPT=[0-9\.]* )/;
	print $1, $2;}
close ASSIGNMENT;


Your indentation is really confusing here - you didn't indent after the first {, indented after the second {, and didn't unindent after the first }. I won't advocate any particular rules for which line to put the {braces} on or how many spaces/tabs to indent or anything like along those lines, but lines at the same level of indentation should be in the same set of braces.

So, taking everything above into account (how to assign to hashes; using strict, warnings, three-argument open, and lexical filehandles; indenting more clearly), my version of your code is:
use strict;
use warnings;

open my $assignment, '<', "Log.log" or die "Can't open Log.log: $!";

my $count = 0;
my %results;
while (my $record = <$assignment>) {
  if ($record =~ /INext-DROP/) {
    $count++;
  }
  $record =~ /(SRC=[0-9\.]* ).*(DPT=[0-9\.]* )/;
  my ($src, $dpt) = ($1, $2);
  $results{$src} = $dpt;
}
close $assignment;



Note that this is using the %results hash to store a simple map of SRC=addr to DPT=addr. If the same SRC=addr value appears more than once in the input, each subsequent appearance will overwrite the previous one rather than appending the new port to the existing result. It is not a full solution to the assignment, it just does exactly the same thing as the code you posted, with the exception of naming the SRC/DPT information and then putting it into a hash rather than printing it.

I will add that the advice given in the assignment regarding "each" and "foreach" is good advice. The "each" command can look very handy, but there are some problems with how it's implemented which are severe enough that many well-respected gurus in the Perl community consider it to be too dangerous to use in production code. Use "foreach" instead.

Bonus points from me for using [0-9\.]* in your regex instead of the non-greedy quantifier suggested in the assignment text. Non-greedy quantifiers are seriously overused in cases where they're not needed (they very rarely actually are needed) and they can kill regex performance quite easily.

Anyhow, if you run into any more walls or want general advice on Perl, just post here and I'm happy to help. Welcome aboard and happy hacking!
Was This Post Helpful? 0
  • +
  • -

#3 stsmiley   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 18-November 09

Re: stuck on creating hash table in perl

Posted 09 March 2010 - 02:20 PM

thanks a lot man that really helped, i think i got it all if i need more help i'll post, thanks again.... oh sorry i got one thing, i have it at the end calculating an average of the number of ports each ip scanned, the number comes out like 2.00638977635783 and i want it to 2 decimal places, do u know by chance how to do that. thanks
Was This Post Helpful? 0
  • +
  • -

#4 dsherohman   User is offline

  • Perl Parson
  • member icon

Reputation: 227
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: stuck on creating hash table in perl

Posted 10 March 2010 - 05:02 AM

View Poststsmiley, on 09 March 2010 - 09:20 PM, said:

i have it at the end calculating an average of the number of ports each ip scanned, the number comes out like 2.00638977635783 and i want it to 2 decimal places, do u know by chance how to do that. thanks


Take a look at the docs for sprintf to get all the details, but, for that specific case, you'd use
my $rounded = sprintf '%0.2f', $raw;

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1