in reply to newbie question on HoH manipulation

You're using each, but throwing away the benefit of getting the value along with the key, and looking it up in the original hash instead, several times. There are several temporary variables you can get rid of, and unless you need them elsewhere (which I'd be wary of), the scope for your essential variables can be kept much narrower. Personal preference of mine: use fewer brackets and more spaces instead.
my %reasons; while (my($city, $code_info) = each %$switch_hash) { my ($code, $date_info) = %$code_info; while(my ($date, $reason) = each %$date_info) { next unless $reason =~ /^(\d+):(.*)/; $date_info->{$date} = $1; $reasons{"$city:$date"} = $2; } }
If you're sure the hash will only have one entry, you can store the code along with the name in the toplevel hash key and save yourself a lot of dereferencing:
my $switch_hash = { 'Washington:uslecwas5e1' => { '01-AUG-2002' => '' }, 'Charleston:uslecchst5e1' => { '01-AUG-2002' => '' }, 'Richmond:uslecric5e1' => { '01-AUG-2002' => '' }, # ...
You could also store that code in an altogether separate hash elso keyed on the same city names. Or you could store it in a special key of the subhash that doesn't contain a valid date, like
my $switch_hash = { 'Washington' => { CODE => 'uslecwas5e1', '01-AUG-2002' => '' }, # ...
and write something like
my %reasons; while (my($city, $info) = each %$switch_hash) { while(my ($date, $reason) = each %$info) { next unless $reason =~ /^(\d+):(.*)/ and $date ne 'CODE'; $info->{$date} = $1; $reasons{"$city:$date"} = $2; } }

Makeshifts last the longest.