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/