On Jan 22, 2008 8:49 PM, Vahid Moghaddasi <[EMAIL PROTECTED]> wrote:
> Hi,
> I have a very strange problem (to me anyways). I have the following
> subroutine to sort unique a UNIX password file based on UID and
> username. But the problem is that some of the users get disappeared
> the output password file. I couldn't figure out the pattern of user
> disappearance but always the same few users are filtering.
> Can someone please take a look at my code and tell me why is it
> messing with me? Any suggestion to rewrite it is also welcome. Thank
> you all.
>
>
> sub Sort {
> my ($infile,$outfile) = @_;
> my @unique = ();
> my %seen = ();
>
> open my $tmp_out, '>', "$outfile"
> or die "could not write the sorted list: $!";
>
> open my $tmp_in, '<', "$infile"
> or die "could not open $infile to sort: $!";
>
> while (<$tmp_in>) {
> next if (m/^#/); # Skip comments
> next if (m/^\s*$/); # Skip blank lines
> my $uname = (split /:/)[0]; # username
> my $uid = (split /:/)[2]; # uid
> next if $seen{ $uid }++;
> next if $seen{ $uname }++;
> push @unique, $_;
> }
> print $tmp_out @unique;
> print "DEBUG: Finishing Sort function.\n" if $DEBUG;
> }
snip
Off hand I think that would only happen if the user name or the uid
was the same for some of your users. Can you present a cleaned up
version of your data the exhibits the problem? Also, You might want
to rewrite your loop more compactly and avoid duplicate calls to
split:
Warning, the following code is untested
#this function does not sort anything so Sort is a bad name
#also Perl functions don't normally have uppercase letters
sub make_passwd_unique {
my ($infile, $outfile) = @_;
#$out and $in are only scoped to this function, there is no need
for the tmp_ prefix
#also, it is handy to print the name of the file that errored
open my $out, '>', "$outfile"
or die "could not write to $out: $!";
open my $in, '<', "$infile"
or die "could not open $infile to sort: $!";
#declare variables close to where they are used, not at the top
my @unique;
my %seen;
while (<$in>) {
#skip comments and blank lines
next if /^#/ || /^\s*$/; #the m is only needed if you
are using a delimiter other than /
my ($uname, $uid) = (split /:/)[0,2]; #use a slice
instead of calling split twice (hey that rhymed!)
#if uid was seen then the uname would never be marked as seen
#this may not be a bug, but if so it should be
documented and you should revert to your old code
$seen{ $uid }++;
$seen{ $uname }++;
next if $seen{uid} > 1 || $seen{$uname} > 1;
print $out; #why save the data and then print it? Print as you go
}
print "DEBUG: Finishing make_passwd_unique function.\n" if $DEBUG;
}
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/