in reply to Re^5: Perl Builds an LDIF
in thread Perl Builds an LDIF

Humbled, I return for wisdom. The while statements are erratic, my wish is to have a 1to1 relationship between the while statements and the input files, yet the 2nd while <MGR> will pull results for 50 lines before the first while <PERSON> runs again. I wish to read iteratively <PERSON> one line at a time, then print @lines, then read iteratively <MGR>, one line at a time, resulting in a four lines written to OUT or buildAD.ldif.

Also, perl throws an error on the second $_ use; how else may it be defined as I wish to place the next line from <MGR> file into the filter?

Error reads: Use of uninitialized value $_ in pattern match (m//) at build4.pl line 48, <MGR> line 120 (#1)(W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables.

I am also puzzled why print OUT (@lines) does not print the contents of LDIFA after each line of <PERSON> is processed (instead it is printing erratically to OUT). And, why OUT fails in Net::LDAP::LDIF->new( "OUT", "a", wrap=>40 );, I am forced to hardcode "buildAD.ldif" instead of OUT.

my $ldap = Net::LDAP->new("$HOST", port=>389) or die "$@"; my $dn = $ldap->bind("$ADMIN", password=>"$PWD"); my $dnm = $ldap->bind("$ADMIN", password=>"$PWD"); my @attr = "1.1"; my $result = Net::LDAP::LDIF->new( "buildAD.ldif", "a", wrap=>40 ); my @lines = (<LDIFA>); while (<PERSON>) { chomp; $dn = $ldap->search( #return only the employeeID DN base => "$BASEDN", filter => "(&(objectClass=user)(employeeID=$_))", scope => "sub", attrs => [@attr] ); next unless $dn; # Make sure something is returned while( my $entry = $dn->pop_entry() ) { $result->write_entry($entry); if ( $result != /dn:/ ) { print OUT (@lines); } while (<MGR>) { chomp; $dnm = $ldap->search( #return only the manager DN base => "$BASEDN", filter => "(&(objectClass=user)(employeeID=$_))", scope => "sub", attrs => [@attr] ); next unless $dnm; # Make sure something is returned while( my $entry = $dnm->pop_entry() ) { $result->write_entry($entry); } } } } $dn = $ldap->unbind; #session ends $dnm = $ldap->unbind; #session ends close OUT2 or die "Cannot close in-memory file: $!"; close OUT or die "Cannot close in-memory file: $!"; close MGR or die "Cannot close in-memory file: $!"; close PERSON or die "Cannot close in-memory file: $!"; close LDIFA or die "Cannot close in-memory file: $!";

Replies are listed 'Best First'.
Re^7: Perl Builds an LDIF
by Corion (Patriarch) on Jun 16, 2010 at 20:37 UTC

    If you find yourself having problems with nested loops, it helps to indent your code so the structure becomes clearer:

    while (<PERSON>) { chomp; $dn = $ldap->search( #return only the employeeID DN base => "$BASEDN", filter => "(&(objectClass=user)(employeeID=$_))", scope => "sub", attrs => [@attr] ); next unless $dn; # Make sure something is returned while( my $entry = $dn->pop_entry() ) { $result->write_entry($entry); if ( $result != /dn:/ ) { print OUT (@lines); } while (<MGR>) { ...

    could be reindented as

    while (<PERSON>) { chomp; $dn = $ldap->search( #return only the employeeID DN base => "$BASEDN", filter => "(&(objectClass=user)(employeeID=$_))", scope => "sub", attrs => [@attr] ); next unless $dn; # Make sure something is returned while( my $entry = $dn->pop_entry() ) { $result->write_entry($entry); if ( $result != /dn:/ ) { print OUT (@lines); } while (<MGR>) { ...

    So, you'll see that once you've read to the end of MGR, you'll still have lines in PERSON. Maybe you want to look up data from the contents of MGR? Then a hash is a better structure:

    my %manager; while (<MGR>) { $manager{ $_ } = $ldap->search(...); # return only the manager DN }; while (<PERSON>) { ... # you never seem to use the information from MGR here... };
Re^7: Perl Builds an LDIF
by NetWallah (Canon) on Jun 16, 2010 at 22:22 UTC
    In addition to Corion's wise words,

    Your code:

    if ( $result != /dn:/ )
    probably does not do what you think it does - and I'm curious to know what you think it does.
    That is probably why you are puzzled about the contents out OUT.

    You probably want to see if $entry contains "dn" and negate that:

    if ( $entry !~ /dn:/ )

         Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

      Temporarily, I am working on different code to achieve the same result. So I may better understand Perl, I submit the following code, albeit not working. I gratefully await your expertise on why it does not work. Grateful for your expertise. This code erractically outputs to OUT. Where should chomp; go in this example? Both PERSON and MGR have an equal number of lines. The desired result is:

      line1 from PERSON changetype: modify replace: manager line1 from MGR line2 from PERSON changetype: modify replace: manager line2 from MGR ...etc... #! perl -slw use strict; use warnings; use diagnostics; use constant batchdir => "c:\temp10"; open (PERSON,"f1"); open (MGR,"f2"); open OUT, ">", "buildAD.ldif" or die "Cannot write to 'buildAD.ldif': +$!"; truncate (OUT, 0); my $line; my $line2; while ($line = <PERSON>) { #chomp; my @dn1 = split(/\s+/,$line); my $count = scalar(@dn1); print OUT "$line"; print OUT "changetype: modify"; print OUT "replace: manager"; while ($line2 = <MGR>) { #chomp; my @dn2 = split(/\s+/,$line2); my $count2 = scalar(@dn2); print OUT $line2, "\n", if ($count == $count2); } } close PERSON; close MGR; close OUT; exit;

      Example data in OUT is here, the extra newline on line 2 should not be there, and all the numbers after 2821 are from <MGR>.

      0104 changetype: modify replace: manager 2821 3682 1129 2050 4054 0755

      Much closer, I've written the following code, albeit also not working, with the same intent. The issue here is that, see OUT example below, only the first line of <PERSON> is read; instead of line1 from <PERSON>, then line1 from <MGR>, then line2 from <PERSON>, then line2 <MGR>, etc.

      while (<PERSON>) { chomp; my $input1 = $_; while (<MGR>) { chomp; my $input2 = $_; print OUT $input1; print OUT "changetype: modify"; print OUT "replace: manager"; print OUT $input2, "\n"; } } exit;

      Output from OUT

      0479 changetype: modify replace: manager 4410 0479 changetype: modify replace: manager 8050 0479 changetype: modify replace: manager 0650 0479 changetype: modify replace: manager 7030 0479 changetype: modify replace: manager 9857 0479 changetype: modify replace: manager 4380
        You are, once again, nesting loops when you do not intend to.

        For better control of loops, separate the "loop" part from "Read input" for "MGR":

        while (defined my $input1=<PERSON>) { my $input2 = <MGR> or die "No corresponding MGR for $input1"; chomp $input1; # Are you sure you want to chomp ? If so, you probably need \n + when printing chomp $input2; print OUT $input1; print OUT "changetype: modify"; print OUT "replace: manager"; print OUT $input2, "\n"; }

             Syntactic sugar causes cancer of the semicolon.        --Alan Perlis