If you find yourself writing essentially the same code multiple times consider using a subroutine. Consider:
#!/usr/bin/perl
use warnings;
use strict;
my $mode = fetch('Enter mode', 1);
while (my $raw_wwn = fetch($mode eq 'a' ? "wwn (no ':')" : "wwn with '
+:'")) {
if ($mode eq 'a') {
if ($raw_wwn =~ /[^0-9a-fA-F]{16}$/) {
print "Invalid Length Or Incorrect Format\n";
} else {
print join (":", unpack ("(a2)*", lc ($raw_wwn))), "\n";
}
next;
}
if ($raw_wwn =~ /[^:a-fA-F0-9]{23}$/) {
print "Invalid Length Or Incorrect Format\n";
next;
}
$raw_wwn =~ s/://g;
print "$raw_wwn\n";
}
sub fetch {
my ($prompt, $key) = @_;
$prompt .= ' or q to quit' if $prompt;
while (1) {
print <<KEY if $key;
Enter
a for lowercase and colons.
b to do it the other way around.
q to quit
KEY
print "$prompt: " if $prompt;
my $answer = lc <>;
chomp $answer;
exit if $answer eq 'q';
return $answer if $key && $answer =~ /^[ab]$/;
return $answer if ! $key;
print qq{"$answer" is not a valid mode.\n\n};
}
}
In addition to drawing the prompting, input code and initial validation into one place, the code above uses fewer variables and those it does use are declared in the smallest sensible scope. The code also uses "early exits" (the return statements and next statements) to avoid extra levels of indentation and to (hopefully) make the logic flow clearer. Trivial cases (like the quit handling) are dealt with first.
Note the use of consistent indentation. Although I tend to write using this indentation style anyway, my editor is fairly smart about indentation and I use Perl::Tidy as a final pass over the code to clean up anything I've missed. Clear consistent indentation and use of white space helps a lot in making scripts understandable.
True laziness is hard work