If you call push with list arguments, you append the first list with the remaining list(s) in stack wise fashion. Read about push at Perldoc. So your call of push(@table, @row);
is creating a longer @table
list, not a two dimensional array.
You have received several posts that pushing a list reference to @row
as \@row
will create a list of rows, and indeed that works. I tend to do it a little differently. Of course, with Perl, there is always another way to do it!
Syntactically, you can also push an anonymous array reference into the scalar element of a list to create multi dimension list. The most important thing to know about references in Perl is: 1) they are a scalar and 2) they can refer to anything in Perl - code, array, hash, another reference. Spend some time with the Perl Ref Tutorial and this will become more clear. With your code, just add [ ]
around the element you want to be the 2nd dimension in your list, so push(@table, @row);
should be push(@table, [ @row ]);
In the same sense, you put [ ]
around your split so that it becomes push(@table, [ split(/\s*,\s*/, $_) ]);
This will simultaneously perform the split and create an anonymous array to the result.
The specific issue that you have, how to create and access a multi dimensional list, is also treated very well in Tom Christensen's perllol tutorial The solutions to your specific issues with your code are directly dealt with here.
Rewriting your code with the the exact code from Tom's example in perllol, it becomes this:
#!/usr/bin/perl
use strict;
use warnings;
my (@row, @table, $n, $rowref);
while(<DATA>) {
chomp;
# regex to separate CSV (use of a cpan module for CSV STRONGLY advised...
@row = /(?:^|,)("(?:[^"]+|"")*"|[^,]*)/g;
for (@row) {
if (s/^"//) { s/"$//; s/""/"/g; }
}
push(@table, [ @row ]); #Note the [ ] around the list
}
# Now the table is created, print it:
my $rowcnt=0;
foreach $rowref (@table) {
print "row $rowcnt:\n";
$rowcnt++;
print " [ @$rowref ], \n";
}
# You can access the table in the classic [i][j] form:
for my $i ( 0 .. $#table ) {
$rowref = $table[$i];
$n = @$rowref - 1;
for my $j ( 0 .. $n ) {
print "element $i, $j of table is $table[$i][$j]\n";
}
}
# You can format it:
for my $i ( 0 .. $#table ) {
print "$table[$i][0] $table[$i][1]\n";
print "$table[$i][2]\n";
print "$table[$i][3], $table[$i][4] $table[$i][5]\n\n";
}
__DATA__
Mac,Doe,120 jefferson st.,Riverside, NJ, 08075
Jack,McGinnis,220 hobo Av.,Phila, PA,09119
"John ""Da Man""",Repici,120 Jefferson St.,Riverside, NJ,08075
Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234
,Blankman,,SomeTown, SD, 00298
"Joan ""Joan, the bone""",Jett,"9th, at Terrace plc",Desert City,CO,00123