I think this is what you are trying to achieve. I've commented each line so that you can understand exactly what's going on there.
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Carp 'fatalsToBrowser';
my $query = CGI->new;
print $query->header;
my $usedpw = "logfile.txt" ;
my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw(! @ $ % ^ & *) );
# opening for reading
open(USEDPW, "<", $usedpw) or die $!;
# shared lock
flock USEDPW, 1;
# read entire file into array, one line per element
my @usedpw = <USEDPW>;
# close the file
close(USEDPW);
# remove new line chars from passwords
chomp @usedpw;
my $pw;
my $used;
# loop generating passwords until we create one that's unique
do {
# generate a password
$pw = join @chars[map{rand @chars} (1..17)];
# assume it's not used
$used = 0;
# compare generated password to each existing password
for (@usedpw) {
# if the generated password has been used before,
# set the used flag and abort the for loop
$used=1,last if $_ eq $pw;
}
} while ($used);
# display the password
print "Your unique password is: $pw\n";
# open for append (>>) and save the new password
open(USEDPW, ">>", $usedpw) or die $!;
# exclusive lock
flock USEDPW, 2;
# write new password to end of file
print USEDPW "$pw\n";
# close the file
close(USEDPW);
---
print map { my ($m)=1<<hex($_)&11?' ':'';
$m.=substr('AHJPacehklnorstu',hex($_),1) }
split //,'2fde0abe76c36c914586c';