My goal is to ldapsearch for information about the devices registered, and turn the resulting answers into csv format, so that they can be imported into a configuration management database. I have a script that generates data such as:
cn: epcpc5 host: epcpc5 description: research server l: Narnia Data Center cn: epcmsp host: epcmsp description: Service Processor l: Narnia Data Center cn: post62a host: post62a description: network printer keyWords: netprinter l: Narnia Data Center cn: tst401 host: tst401 host: tst401.narnia.org host: srv1ck41 description: Test Application Server env: test keyWords: linuxserver keyWords: nonprod keyWords: localperl keyWords: sudoers l: Data Center, Narnia sysadm1: aslan administratorContactInfo: sciops nsHardwarePlatform: DellR730
I searched the net and found a perl example that did a subset of what I needed for user information. So I because modifying it to handle my cases - combine repeating attributes, such as keyWords into one csv field, quoted and comma deliminted within the quotes, different column names, etc. My code is currently this:
#!/usr/bin/env perl use strict; use warnings; # Bail out if no file is given as an argument. my $ldap_file = shift || usage(); # To save output with extension .csv. my $csv_file = "$ldap_file.csv"; # Preserve order of header labels. my @header = qw(cn host description env keyWords l sysadm1 sysadm2 adm +inistratorContactInfo nsHardwarePlatform version); # Boiler plate to open input and output files handles. open my $in, '<', $ldap_file or die; open my $out, '>', $csv_file or die; # Write the header labels. print $out join (',', @header[0..$#header]), "\n"; # Work engine. { # Record separator is a paragraph representation. local $/="\n\n"; # Process one record at a time. while(my $record = <$in>) { my %data = (); chomp $record; # Remove the record separator. $data{@header} = (); # To label the data. my @entries = split '\n', $record; # Create data entries. # Work with each entry. foreach my $entry (@entries){ if ($entry eq "") { next; } my ($key, $value) = split ":", $entry, 2; # split only by +first equal. if ($key eq "" or $key eq "dn") { next; } if ($value eq "") { print "empty value: entry=$entry\n"; } $value =~ s/^\s+//; # Clean leading spaces. $value =~ s/\s+$//; # Clean trailing spaces. if ( exists $data{$key} ) { $data{$key} .= ("," . $value); } else { $data{$key} = $value; } } # Separate entries with commas. foreach my $key (keys %data) { print "key=$key, value=$data($key)\n"; $data($key) =~ s/(^|$)/"/g if $data($key) =~ /,/; } my $row = join ',', (map{ $data{$_}?$data{$_}:""} @header); # Write to output file. print $out "$row\n"; } } # Dismiss file handles. close $in; close $out; # Feed back to user. print "$csv_file has been saved in the current directory\n"; sub usage { print "Usage: $0 ldapfilename\n"; exit 1; }
When I attempt to run this using perl v5.8.4 I get
Global symbol "$data" requires explicit package name at ./ldap2csv.pl +line 58. Global symbol "$data" requires explicit package name at ./ldap2csv.pl +line 59. syntax error at ./ldap2csv.pl line 59, near "$data(" Global symbol "$data" requires explicit package name at ./ldap2csv.pl +line 59. Execution of ./ldap2csv.pl aborted due to compilation errors.
The line numbers within these messages are these lines
# Separate entries with commas. foreach my $key (keys %data) { print "key=$key, value=$data($key)\n"; $data($key) =~ s/(^|$)/"/g if $data($key) =~ /,/; }
There is a my %data within the while block where all these code is taking place. I don't quite understand what I need to do, when referencing the hash/key to get a value, so that perl strict is happy with the references. The various results I found web searching didn't cover additional safety precautions to be taken in this type of situation. I am hoping someone out there has an answer for me.

In reply to Parsing ldap attributes into a csv by lvirden

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.