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/


Reply via email to