Nick Chettle <mailto:[EMAIL PROTECTED]> wrote:
: I am not 100% sure what this line does. : : push @{ $msgids->{$1} }, $_; : : Is the @{} surrounding the hash used to make push work with a hash? No. We cannot push items onto a hash. We need an array for that. "$msgids->{$1}" is an array reference. It refers to an array reference inside a hash which is, in turn, referenced by a hash reference ("$msgids"). "$msgids->{$1}" is an array reference. The "@{}" allows us to de-reference the reference. As you may recall, an array is a list of items. my @animals = ( 'cat', 'dog' ); Sometimes it is more convenient to use a scalar variable than an array variable. my $animals_ref = [EMAIL PROTECTED]; In fact, we don't really need the original array. We can create the reference and operate on just it. We use "[]" to define an array without a name. my $animals_ref = [ 'cat', 'dog' ]; To add an item to the end of an array, we use "push". my @animals = ( 'cat', 'dog' ); push @animals, 'horse'; my $animals_ref = [ 'cat', 'dog' ]; push @{ $animals_ref }, 'horse'; We could have pushed everything onto the array. my @animals; push @animals, 'cat'; push @animals, 'dog'; push @animals, 'horse'; my $animals_ref; push @{ $animals_ref }, 'cat'; push @{ $animals_ref }, 'dog'; push @{ $animals_ref }, 'horse'; my $msgids; push @{ $msgids->{Fred} }, 1005; push @{ $msgids->{Fred} }, 1058; push @{ $msgids->{Fred} }, 2587; In the example above, there exists a reference to a hash named "$msgids". Autovivification allows the hash to add keys when a new one is used. So, if $1 is a new key it will be added to the hash, otherwise we will use an existing key. Since $msgids is a reference hash of arrays. But hashes can only contain scalar values, you say. No problem, the arrays we store in the hash are actually array references. So technically, $msgids is a reference to a hash of array references. Pretty complicated, huh? Read perlref for an intro to perl data structures. : Also, why do you need -> Because the author chose to use a hash reference to a hash. my $msgids; while (<MAILLOG>) { if (/$email/) { if (/([A-Z1-9]{8})/) { push @{ $msgids->{$1} }, $_; } } } : and can't just do $msgids{$1}, $_; ? my %msgids; while (<MAILLOG>) { if (/$email/) { if (/([A-Z1-9]{8})/) { push @{ $msgids{$1} }, $_; } } } : I made a slight change to make your addition work in that I added () : around the regex so that $1 would work - is there any reason to use : this over $&? : : So, AFAICS, your addition creates a hash (Using the message id's as : the key) and puts the associated line from the log in the hash. So I : thought I could simply do: : : for (sort keys %msgids) { : print $msgids{$_}; : } : : To print each line found. For some reason this returns nothing. You didn't turn on strict or warnings. There is no %msgids. You would get all sorts of warnings otherwise. This should work. #!/usr/bin/perl use strict; use warnings; print "Please enter an e-mail address: "; chomp( my $email = <STDIN> ); my $file = '/var/log/maillog'; open MAILLOG, $file or die qq(Cannot open "$file": $!); my %msgids; while (<MAILLOG>) { if (/$email/) { if (/([A-Z1-9]{8})/) { push @{ $msgids->{$1} }, $_; } } } close MAILLOG; foreach my $key (sort keys %{ $msgids } ) { print $msgids->{ $key }; } __END__ OR: #!/usr/bin/perl use strict; use warnings; print "Please enter an e-mail address: "; chomp( my $email = <STDIN> ); my $file = '/var/log/maillog'; open MAILLOG, $file or die qq(Cannot open "$file": $!); my %msgids; while (<MAILLOG>) { if (/$email/) { if (/([A-Z1-9]{8})/) { push @{ $msgids{$1} }, $_; } } } close MAILLOG; foreach my $key (sort keys %msgids) { print $msgids{ $key }; } __END__ HTH, Charles K. Clarkson -- Mobile Homes Specialist 254 968-8328 -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>