Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Why do I get uninitialized value in substitution (s///) in my array?

by xjlittle (Beadle)
on Aug 10, 2009 at 02:12 UTC ( [id://787223]=perlquestion: print w/replies, xml ) Need Help??

xjlittle has asked for the wisdom of the Perl Monks concerning the following question:

Hi
I am trying to set new passwords for new users in an ldif list. The passwords are currently set to xyz456. When I run the script and print the array element $genpass[0] I don't get the error. When I run it with the susbstitution I get the uninitialized value error. Please shed some enlightenment for me gracious monks.
#!/usr/bin/perl -w use strict; my $p = 1; my @genpass; my $genpass; my $pass = "/home/v0x9849/scripts/new.pass"; open (PASS, ">", $pass) or die "Cannot open $pass: $!"; while ( $p < 53 ){ @genpass = generatePassword(10); print PASS "@genpass \n"; $p++; } close PASS; open (PASS, $pass) or die "Cannot open $pass: $!"; @genpass = (<PASS>); my $a; my $users = "/home/v0x9849/scripts/new.users"; open (USERS, $users) or die "Cannot open $users: $!"; my @nup = (<USERS>); close USERS; open (USERS, ">", $users) or die "Cannot open $users: $!"; foreach (@nup){ # print "$genpass[0]\n"; <==this works s/xyz456/$genpass[0]/; <==this gets uninitialized #print USERS; $a = shift(@genpass); } close USERS; #print generatePassword(10) . "\n"; #exit; sub generatePassword { my $length = shift; my $password = ""; my $possible = 'abcdefghijkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWX +YZ'; while (length($password) < $length) {$password .= substr($possible, (i +nt(rand(length($possible)))), 1);}return $password}
Grandfather, here is the data file. This is repeated 52 times with a blank line between each user's info. This line is constant with all entries and in the same place each time: userPassword: xyz456
__DATA__ dn: uid=1234567,ou=people,dc=abc,o=oursite.com objectClass: posixAccount objectClass: shadowAccount objectClass: account objectClass: top uid: 1234567 cn: 1234567 uidNumber: 31472 gidNumber: 7546 gecos: First Last,ABCDEFG297,####### homeDirectory: /home/1234567 loginShell: /bin/csh userPassword: xyz456 <==constant line

@ig, @graff There are 728 lines total including blanks between each user's data entry. When I set the iterations to 728 it made the file 0 bytes. However this does seem reasonable as it would have to go through each line. Any ideas on how to prevent it from going to 0 bytes?
@desemondo The only thing copied is the password generation script which is not the issue. When I tried your suggestion with 53 iteration I got the same error. When I tried it with 728 it also made the file 0 bytes.
@jwkrahn That may work but we are not allowed to add modules to our workstations.

Replies are listed 'Best First'.
Re: Why do I get uninitialized value in substitution (s///) in my array?
by GrandFather (Saint) on Aug 10, 2009 at 02:48 UTC

    Although you show us how you generate the password list, which doesn't seem relevant at all, you don't provide us with sample failing user list data. Your substitution acts on $_ (the default variable) which takes the value of each entry in @nup in turn. If you see an undefined variable warning then most likely there is an undef in @nup nad that implies something bad about your users data.

    Try providing a sample user data file with failing data in a __DATA__ section following your sample program. Something like:

    use warnings; use strict; my @genpass = (1 .. 3); my @nup = (<DATA>); foreach (@nup) { s/xyz456/$genpass[0]/; shift (@genpass); } __DATA__ 1 2 3

    True laziness is hard work
      Though it's certainly well intentioned and not unreasonable to draw attention to the content of the "user list" data file, I can't imagine how the OP code could be getting an "undef" element in the @nup array.

      Have you ever encountered a situation where @array = <FILE> produces an undef element in the array? What sort of condition in a data file would cause that?

      I think ig's question below is more likely to be on the mark.

Re: Why do I get uninitialized value in substitution (s///) in my array?
by ig (Vicar) on Aug 10, 2009 at 02:59 UTC

    Is it possible that when you try to substitute the passwords your ldif file has more than 53 lines? You are shifting one password off @genpass for each line in your ldif file. This is one password for each user only if your ldif file has one line for each user.

      ig,
      That worked the 2nd time that I tried it. I'm not sure why it didn't work the first time.
      Thanks!

        I would probably write your script something like the following, avoiding the problem of how many passwords to generate.

        use strict; use warnings; my $users = "new.users"; open(my $in, '<', $users) or die "Cannot open $users: $!"; my $tmp = $users . '.tmp'; open(my $out, '>', $tmp) or die "Cannot open $tmp: $!"; foreach (<$in>) { if(/^userPassword: xyz456$/) { my $pw = generatePassword(10); s/^userPassword: xyz456/userPassword: $pw/; } print $out "$_"; } close($out); close($in); unlink($users) or die "unlink($users): $!"; rename($tmp, $users) or die "rename($tmp, $users): $!"; exit(0); sub generatePassword { my $length = shift; my $password = ""; my $possible = 'abcdefghijkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRST +UVWXYZ'; while (length($password) < $length) { $password .= substr($possible, (int(rand(length($possible)))), 1); } return $password }
Re: Why do I get uninitialized value in substitution (s///) in my array?
by jwkrahn (Abbot) on Aug 10, 2009 at 03:34 UTC

    It looks like you want something like this:

    #!/usr/bin/perl use warnings; use strict; use Tie::File; my $users = '/home/v0x9849/scripts/new.users'; tie my @nup, 'Tie::File', $users or die "Cannot open $users: $!"; for ( @nup ) { if ( $_ eq 'xyz456' ) { $_ = generatePassword( 10 ); } } untie @nup; sub generatePassword { my $length = shift; my @possible = ( 'a' .. 'k', 'm', 'n', 'p' .. 'z', 2 .. 9, 'A' .. +'H', 'J' .. 'N', 'P' .. 'Z' ); return join '', map $possible[ rand @possible ], 1 .. $length; }
Re: Why do I get uninitialized value in substitution (s///) in my array?
by desemondo (Hermit) on Aug 10, 2009 at 03:38 UTC
    It would seem that a lot of this script is copied and pasted. From my own experiences, this usually ends up taking far more time debugging, than starting from scratch...

    Without seeing more of your script and data, (please reply with further info), I suspect that you might simply need to chomp the $_ assigned from @nup.


    Eg.

    open (USERS, ">", $users) or die "Cannot open $users: $!"; foreach (@nup){ # print "$genpass[0]\n"; <==this works s/xyz456/$genpass[0]/; <==this gets uninitialized #print USERS; $a = shift(@genpass); }
    becomes

    open (USERS, ">", $users) or die "Cannot open $users: $!"; foreach (@nup){ chomp; print "$genpass[0]\n"; s/xyz456/$genpass[0]/; #print USERS; $a = shift(@genpass); }
Re: Why do I get uninitialized value in substitution (s///) in my array?
by Popcorn Dave (Abbot) on Aug 10, 2009 at 21:47 UTC
    One small thing that could come back to bite you in the butt down the road is using $a for a variable since $a and $b are special variables.

    I'd change it to something a bit more meaningful so not only that you'll remember what it does when you look at the code 6 months from now but you won't get messed up if you use the <=> operator in the program down the road.


    To disagree, one doesn't have to be disagreeable - Barry Goldwater

Re: Why do I get uninitialized value in substitution (s///) in my array?
by ikegami (Patriarch) on Aug 12, 2009 at 14:58 UTC
    s/xyz456/$genpass[0]/;

    means

    $_ =~ s/xyz456/$genpass[0]/;

    You checked whether $genpass[0] was undef or not, but you didn't check $_.

Re: Why do I get uninitialized value in substitution (s///) in my array?
by desemondo (Hermit) on Aug 11, 2009 at 01:52 UTC
    This seems to work fine, albeit I wasn't able to reproduce the error you were getting of uninitialised value. If you still get the error, maybe try dumping both @nup and @genpass to separate text files and look for special control characters. Also, make sure the number of elements in each array tally with what your expecting.
    #!/usr/bin/perl -w use strict; use warnings; my @genpass; my $pass = "new.pass"; open (PASS, ">", $pass) or die "Cannot open $pass: $!"; my $p = 1; while ( $p < 53 ){ @genpass = generatePassword(10); print PASS "@genpass \n"; $p++; } close PASS; open (PASS, $pass) or die "Cannot open $pass: $!"; @genpass = (<PASS>); chomp @genpass; print scalar (@genpass) , " <- genpass\n"; my $users = "new.users"; #open (USERS, "<", $users) or die "Cannot open $users: $!"; my @nup = (<DATA>); print scalar (@nup) , " <- nup\n"; #close USERS; open (USERS, ">", $users) or die "Cannot open $users: $!"; foreach my $line (@nup){ $line =~ s/xyz456/$genpass[0]/; print USERS $line; shift(@genpass); } close USERS; sub generatePassword { my $length = shift; my $password = ""; my $possible = 'abcdefghijkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRST +UVWXYZ'; while (length($password) < $length) { $password .= substr($possible, (int(rand(length($possible)))), + 1); } return $password; } __DATA__ dn: uid=1234567,ou=people,dc=abc,o=oursite.com objectClass: posixAccount objectClass: shadowAccount objectClass: account objectClass: top uid: 1234567 cn: 1234567 uidNumber: 31472 gidNumber: 7546 gecos: First Last,ABCDEFG297,####### homeDirectory: /home/1234567 loginShell: /bin/csh userPassword: xyz456 dn: uid=1234567,ou=people,dc=abc,o=oursite.com objectClass: posixAccount objectClass: shadowAccount objectClass: account objectClass: top uid: 1234567 cn: 1234567 uidNumber: 31472 gidNumber: 7546 gecos: First Last,ABCDEFG297,####### homeDirectory: /home/1234567 loginShell: /bin/csh userPassword: xyz456 dn: uid=1234567,ou=people,dc=abc,o=oursite.com objectClass: posixAccount objectClass: shadowAccount objectClass: account objectClass: top uid: 1234567 cn: 1234567 uidNumber: 31472 gidNumber: 7546 gecos: First Last,ABCDEFG297,####### homeDirectory: /home/1234567 loginShell: /bin/csh userPassword: xyz456

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://787223]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-19 20:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found