I think that
$SIG{'__WARN__'} is the wrong approach to this problem.
The warning-generating condition can be detected before the warning occurs, so why not detect it yourself
and handle it more cleanly than with an action-at-a-distance
%SIG handler? Here are two methods that I frequently use:
-
Warn and skip as soon as the line is known to be bad. In your case, do it when the URL RE fails.
This method tends to be efficient, since any parsing code lower in the loop is bypassed on error.
However, it only reports the first parse error for any particular line, and requires warn/skip code at each parse step that could fail.
$entry[6] =~ m{^http://.*v1=(.*)&v2=(.*)&v3=.*$} or do {
warn "Skipping unparseable line $. :\n"
. " http_code: $http_code\n"
. " url: $url\n"
. " edate[0]: $edate[0]\n"
. " edate[1]: $edate[1]\n"
. " edate[2]: $edate[2]\n"
. " edate[3]: $edate[3]\n"
;
next;
};
my $url = "$1$2";
$STATUS{$http_code}{$url}{$edate[0]}{$edate[1]}{$edate[2]}{$edate[3]}+
++;
-
When any element fails to parse, set it to undef. When the time comes to use those elements, then warn/skip if any of them are undefined. In your case, do it just before incrementing %STATUS.
This method produces only one warning per line when multiple parse errors occur, and consolidates all the error handling
(except setting undef) into one place.
my $url = ( $entry[6] =~ m{^http://.*v1=(.*)&v2=(.*)&v3=.*$} )
? "$1$2" : undef ;
# ... More parsing code can go here.
if ( grep {not defined $_} ( $http_code, $url, @edate[0..3] ) ) {
warn "Skipping unparseable line $. :\n"; # ... and dump vars.
next;
}
$STATUS{$http_code}{$url}{$edate[0]}{$edate[1]}{$edate[2]}{$edate[3]}+
++;