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

Your are building new "$result" objects for each PERSON.

Try moving the "new LDIF" to outside of the loop:

my $ldif_OUT = Net::LDAP::LDIF->new( "buildAD.ldif", "a", wrap=>40 ); while (<PERSON>){ chomp; $dn = $ldap->search( #return only the employeeID DN base => "$BASEDN", filter => "(&(objectClass=user)(employeeID=$_))", scope => "sub", attrs => ['1.1'] ); next unless $dn; # Make sure something is returned.. while( my $entry = $dn->pop_entry() ) { $ldif_OUT->write_entry($entry); } print OUT "changetype: modify"; print OUT "replace: manager"; print OUT "manager: dn","\n"; } $dn = $ldap->unbind; #session ends
(Minimalistic error-checking added..)

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

Replies are listed 'Best First'.
Re^6: Perl Builds an LDIF
by rfransix (Novice) on Jun 16, 2010 at 20:22 UTC

    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: $!";

      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... };
      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