Perl array with row header

Here is the csv file file i have:

ServerName, IPAddress, Gateway, Notes
ServerA, 192.168.1.100, 192.168.1.1, This is some server
ServerB, 192.168.1.110, 192.168.1.1, This is some other server
ServerC, 192.168.1.120, 192.168.1.1, This is some other other server

I would like to have the following:

$Servername[0] = ServerA
$IPAddress[0] = 192.168.1.100
...
$Servername[1] = ServerB
...
etc...

The column headers could be any number of columns or names.

Im actually taking the output of wmic on a linux server after querying the windows via WMI.

:wall:

Here is a sample:

$Selection="*";
$WMIClass="Win32_OperatingSystem";
@Output=`wmic --delimiter "," --user "$Username"%"$Password" //$TargetHost \"Select $Selection from $WMIClass\"`;

Which would output something like:

#wmic --user DOMAIN/USERNAME%PASSWORD //Someserver "Select * FROM Win32_LocalTime"

CLASS: Win32_LocalTime
Day|DayOfWeek|Hour|Milliseconds|Minute|Month|Quarter|Second|WeekInMonth|Year
18|2|13|0|20|1|1|56|4|2011

---------- Post updated at 04:16 PM ---------- Previous update was at 03:19 PM ----------

I got it figured out:

$rowcount=0;
foreach (@Output) {
    @line = split(',',$_);
    $colcount=0;
    foreach $col (@Columns) {
        $$col[$rowcount] = $line[$colcount];
        $colcount++;
    }
    $rowcount++;
}

None of our Perl experts are jumping on this, so I guess I'll give it a try. This is what I wrote:

$
$ cat readr
#! /usr/bin/perl -w

$_ = <STDIN>;
chomp;
@fields = split ',';
for ($i=0 ; $i < $#fields; $i++) {
        $fields[$i] =~ s/^ *//;
        print "field $i = $fields[$i] \n";
}

$j = 0;
while (<>) {
        chomp;
        print "line = $_ \n";
        @data = split ',';
        for ($i=0; $i < $#data; $i++) {
                $data[$i] =~ s/^ *//;
                $array = $fields[$i];     # How to combine these
                $$array[$j] = $data[$i];  # two lines?
        }
        $j++;
}

for ($i=0 ; $i <= $#ServerName; $i++) {
        print "ServerName $i = $ServerName[$i] \n";
}
$ ./readr < data1
field 0 = ServerName
field 1 = IPAddress
field 2 = Gateway
line = ServerA, 192.168.1.100, 192.168.1.1, This is some server
line = ServerB, 192.168.1.110, 192.168.1.1, This is some other server
line = ServerC, 192.168.1.120, 192.168.1.1, This is some other other server
ServerName 0 = ServerA
ServerName 1 = ServerB
ServerName 2 = ServerC
$

That last loop is just to prove that I had populated an array called ServerName. Notice the two lines that I commented. I really wanted to combine them into a single line and lose that $array scalar. But I could not find the right syntax. Can anyone kick that ball over the goalline for me?

And no fair rewriting it to use a more sensible data structure. I gave the OP what he asked for. I realize the requirements are a little odd.

You could combine those two lines by the use of braces.

${$fields[$i]}[$j] = $data[$i];

The updated Perl program looks like this -

$
$ cat readr
#! /usr/bin/perl -w
 
$_ = <STDIN>;
chomp;
@fields = split ',';
for ($i=0 ; $i <= $#fields; $i++) {
        $fields[$i] =~ s/^ *//;
        print "field $i = $fields[$i] \n";
}
 
$j = 0;
while (<>) {
        chomp;
        print "line = $_ \n";
        @data = split ',';
        for ($i=0; $i <= $#data; $i++) {
                $data[$i] =~ s/^ *//;
#                $array = $fields[$i];     # How to combine these
#                $$array[$j] = $data[$i];  # two lines?
                ${$fields[$i]}[$j] = $data[$i];  # Like so...
        }
        $j++;
}
 
for ($i=0 ; $i <= $#ServerName; $i++) {
        print "ServerName $i = $ServerName[$i] \n";
}
for ($i=0 ; $i <= $#IPAddress; $i++) {
        print "IPAddress $i = $IPAddress[$i] \n";
}
for ($i=0 ; $i <= $#Gateway; $i++) {
        print "Gateway $i = $Gateway[$i] \n";
}
for ($i=0 ; $i <= $#Notes; $i++) {
        print "Notes $i = $Notes[$i] \n";
}
$
$

And here's a test run -

$
$ # print the data file
$
$ cat data1
ServerName, IPAddress, Gateway, Notes
ServerA, 192.168.1.100, 192.168.1.1, This is some server
ServerB, 192.168.1.110, 192.168.1.1, This is some other server
ServerC, 192.168.1.120, 192.168.1.1, This is some other other server
$
$ # feed it to the Perl program
$
$ ./readr < data1
field 0 = ServerName
field 1 = IPAddress
field 2 = Gateway
field 3 = Notes
line = ServerA, 192.168.1.100, 192.168.1.1, This is some server
line = ServerB, 192.168.1.110, 192.168.1.1, This is some other server
line = ServerC, 192.168.1.120, 192.168.1.1, This is some other other server
ServerName 0 = ServerA
ServerName 1 = ServerB
ServerName 2 = ServerC
IPAddress 0 = 192.168.1.100
IPAddress 1 = 192.168.1.110
IPAddress 2 = 192.168.1.120
Gateway 0 = 192.168.1.1
Gateway 1 = 192.168.1.1
Gateway 2 = 192.168.1.1
Notes 0 = This is some server
Notes 1 = This is some other server
Notes 2 = This is some other other server
$
$

tyler_durden

1 Like

Note that durden_tyler also fixed a bug I had in iterating over the fields. Be sure to use the corrected perl script rather than my initial attempt.

another try:-

perl -F"," -wlane '
(@a = @F) and next if $.==1 ;
$i = 0 ;
map { s/^\s+// ; push @{$_},$F[$i++] } @a ;
END {
map { $j=$_ ; map { print  $_,"[$j]"," = ",${$_}[$j] } @a  ;print "\n" ; } (0 .. $#a-1) ;
}
' infile.txt

:wink:

1 Like

:eek:

Seeing code like this makes me realize that I have quite a ways to go before I master Perl. However it also makes me want to get there. Very impressive work!

Thanks Perderabo appreciated :):):slight_smile: