my %total_bytes;
while (<>) {
my ($source, $destination, $bytes) = split;
$total_bytes{$source}{$destination} += $bytes;
}
for my $source (sort keys %total_bytes) {
for my $destination (sort keys %{ $total_bytes{$source} }) {
print "$source => $destination:",
" $total_bytes{$source}{$destination} bytes\n";
}
print "\n";
}
myhost% perl -d bytecounts bytecounts-in
Loading DB routines from perl5db.pl version 1.19
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(bytecounts:2): my %total_bytes;
DB<1> s
main::(bytecounts:3): while (<>) {
DB<1> s
main::(bytecounts:4): my ($source, $destination, $bytes) = split;
DB<1> s
main::(bytecounts:5): $total_bytes{$source}{$destination} += $bytes;
DB<1> x $source, $destination, $bytes
0 'professor.hut'
1 'gilligan.crew.hut'
2 1250
If you're playing along at home, be aware that each
new release of the debugger works differently than any other, so your
screen probably won't look exactly like this. Also,
if you get stuck at any time, type h for help, or
look at perldoc perldebug.
Let's see what happens just after the next
assignment:
DB<3> s
main::(bytecounts:4): my ($source, $destination, $bytes) = split;
DB<3> s
main::(bytecounts:5): $total_bytes{$source}{$destination} += $bytes;
DB<3> x $source, $destination, $bytes
0 'professor.hut'
1 'lovey.howell.hut'
2 910
DB<4> s
main::(bytecounts:3): while (<>) {
DB<4> x \%total_bytes
0 HASH(0x132dc)
'professor.hut' => HASH(0x37a34)
'gilligan.crew.hut' => 1250
'lovey.howell.hut' => 910
Now you've added bytes flowing from
professor.hut to
lovey.howell.hut. The top-level hash
hasn't changed, but the second-level hash has added
a new entry. Let's continue:
DB<5> s
main::(bytecounts:4): my ($source, $destination, $bytes) = split;
DB<6> s
main::(bytecounts:5): $total_bytes{$source}{$destination} += $bytes;
DB<6> x $source, $destination, $bytes
0 'thurston.howell.hut'
1 'lovey.howell.hut'
2 1250
DB<7> s
main::(bytecounts:3): while (<>) {
DB<7> x \%total_bytes
0 HASH(0x132dc)
'professor.hut' => HASH(0x37a34)
'gilligan.crew.hut' => 1250
'lovey.howell.hut' => 910
'thurston.howell.hut' => HASH(0x2f9538)
'lovey.howell.hut' => 1250
Ah, now it's getting interesting. A new entry in the
top-level hash has a key of thurston.howell.hut,
and a new hash reference, autovivified initially to an empty hash.
Immediately after the new empty hash was put in place, a new
key/value pair was added, indicating 1250 bytes transferred from
thurston.howell.hut to
lovey.howell.hut. Let's step some
more:
DB<8> s
main::(bytecounts:4): my ($source, $destination, $bytes) = split;
DB<8> s
main::(bytecounts:5): $total_bytes{$source}{$destination} += $bytes;
DB<8> x $source, $destination, $bytes
0 'professor.hut'
1 'lovey.howell.hut'
2 450
DB<9> s
main::(bytecounts:3): while (<>) {
DB<9> x \%total_bytes
0 HASH(0x132dc)
'professor.hut' => HASH(0x37a34)
'gilligan.crew.hut' => 1250
'lovey.howell.hut' => 1360
'thurston.howell.hut' => HASH(0x2f9538)
'lovey.howell.hut' => 1250
Now you're adding in some more bytes from
professor.hut to
lovey.howell.hut, reusing the existing value
place. Nothing too exciting there. Let's keep
stepping:
DB<10> s
main::(bytecounts:4): my ($source, $destination, $bytes) = split;
DB<10> s
main::(bytecounts:5): $total_bytes{$source}{$destination} += $bytes;
DB<10> x $source, $destination, $bytes
0 'ginger.girl.hut'
1 'professor.hut'
2 1218
DB<11> s
main::(bytecounts:3): while (<>) {
DB<11> x \%total_bytes
0 HASH(0x132dc)
'ginger.girl.hut' => HASH(0x297474)
'professor.hut' => 1218
'professor.hut' => HASH(0x37a34)
'gilligan.crew.hut' => 1250
'lovey.howell.hut' => 1360
'thurston.howell.hut' => HASH(0x2f9538)
'lovey.howell.hut' => 1250
DB<12> s
main::(bytecounts:4): my ($source, $destination, $bytes) = split;
DB<12> s
main::(bytecounts:5): $total_bytes{$source}{$destination} += $bytes;
DB<12> x $source, $destination, $bytes
0 'ginger.girl.hut'
1 'maryann.girl.hut'
2 199
DB<13> s
main::(bytecounts:3): while (<>) {
DB<13> x \%total_bytes
0 HASH(0x132dc)
'ginger.girl.hut' => HASH(0x297474)
'maryann.girl.hut' => 199
'professor.hut' => 1218
'professor.hut' => HASH(0x37a34)
'gilligan.crew.hut' => 1250
'lovey.howell.hut' => 1360
'thurston.howell.hut' => HASH(0x2f9538)
'lovey.howell.hut' => 1250
Now you've added a second destination to the hash
that records information for all bytes originating at
ginger.girl.hut. Because that was the final line
of data (in this run), a step brings you down to the lower
foreach loop:
DB<14> s
main::(bytecounts:8): for my $source (sort keys %total_bytes) {
DB<14> x sort keys %total_bytes
0 'ginger.girl.hut'
1 'professor.hut'
2 'thurston.howell.hut'
This is the list the foreach now scans. These are
all the sources for transferred bytes seen in this particular
logfile. Here's what happens when you step into the
inner loop:
DB<15> s
main::(bytecounts:9): for my $destination (sort keys %{ $total bytes{
$source} }) {
At this point, you can determine from the inside out exactly what
values will result from the list value from inside the parentheses.
Let's look at them:
DB<15> x $source
0 'ginger.girl.hut'
DB<16> x $total_bytes{$source}
0 HASH(0x297474)
'maryann.girl.hut' => 199
'professor.hut' => 1218
DB<18> x keys %{ $total_bytes{$source } }
0 'maryann.girl.hut'
1 'professor.hut'
DB<19> x sort keys %{ $total_bytes{$source } }
0 'maryann.girl.hut'
1 'professor.hut'