[root@dou ~]# cat s.pl
#!/bin/perl my %table; while(<>) { chomp; my ($city,$country) = split(/, /); $table{$country} = [] unless exists $table{$country}; push @{$table{$country}}, $city; } foreach $country (sort keys %table) { print "$country: "; my @cities = @{$table{$country}}; print join', ',sort @cities; print ".\n"; } [root@dou ~]# [root@dou ~]# cat test Chicago, USA Frankfurt, Germany Berlin, Germany Washington, USA Helsinki, Finland New York, USA [root@dou ~]# perl s.pl test Finland: Helsinki. Germany: Berlin, Frankfurt. USA: Chicago, New York, Washington. If there's already an entry in %table for the current $country, then nothing is different. Line 6 will locate the value in $table{$country}, which is a reference to an array, and push $city into the array. But what does it do when $country holds a key, say Greece, that is not yet in %table? This is Perl, so it does the exact right thing. It sees that you want to push Athens onto an array that doesn't exist, so it helpfully makes a new, empty, anonymous array for you, installs it into %table, and then pushes Athens onto it. This is called 'autovivification'--bringing things to life automatically. Perl saw that they key wasn't in the hash, so it created a new hash entry automatically. Perl saw that you wanted to use the hash value as an array, so it created a new empty array and installed a reference to it in the hash automatically. And as usual, Perl made the array one element longer to hold the new city name. The Rest ^ I promised to give you 90% of the benefit with 10% of the details, and that means I left out 90% of the details. Now that you have an overview of the important parts, it should be easier to read the perlref manual page, which discusses 100% of the details. Some of the highlights of perlref: You can make references to anything, including scalars, functions, and other references. In Use Rule 1, you can omit the curly brackets whenever the thing inside them is an atomic scalar variable like $aref. For example, @$aref is the same as @{$aref}, and $$aref[1] is the same as ${$aref}[1]. If you're just starting out, you may want to adopt the habit of always including the curly brackets. This doesn't copy the underlying array: $aref2 = $aref1; You get two references to the same array. If you modify $aref1->[23] and then look at $aref2->[23] you'll see the change. To copy the array, use $aref2 = [@{$aref1}]; This uses [...] notation to create a new anonymous array, and $aref2 is assigned a reference to the new array. The new array is initialized with the contents of the array referred to by $aref1. Similarly, to copy an anonymous hash, you can use $href2 = {%{$href1}}; To see if a variable contains a reference, use the ref function. It returns true if its argument is a reference. Actually it's a little better than that: It returns HASH for hash references and ARRAY for array references. If you try to use a reference like a string, you get strings like ARRAY(0x80f5dec) or HASH(0x826afc0) If you ever see a string that looks like this, you'll know you printed out a reference by mistake. A side effect of this representation is that you can use eq to see if two references refer to the same thing. (But you should usually use == instead because it's much faster.) You can use a string as if it were a reference. If you use the string "foo" as an array reference, it's taken to be a reference to the array @foo. This is called a soft reference or symbolic reference. The declaration use strict 'refs' disables this feature, which can cause all sorts of trouble if you use it by accident. You might prefer to go on to perllol instead of perlref; it discusses lists of lists and multidimensional arrays in detail. After that, you should move on to perldsc; it's a Data Structure Cookbook that shows recipes for using and printing out arrays of hashes, hashes of arrays, and other kinds of data.