Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monks,

I'm new to Perl and have a naive question about a small program.

If I run the following program with data embeded in the program, the output is fine.


my $horiz_data = <<"HORIZ" ;
||||01/01/2007|01/02/2007|01/03/2007|06/29/2007|
|JOHN DOE|Event1|SUB|PARTY|CLASS|WORK|VACATION|
|JOHN D0E|Event2|SUB|CLASS|CLASS|WORK|PARTY|
|JANE DOE|Event1|SUB|PARTY|CLASS|WORK|VACATION|
|JANE DOE|Event2|SUB|CLASS|CLASS|WORK|PARTY|
HORIZ

my @horiz = split "\n", $horiz_data;

my @dates = split '\|', shift @horiz;


shift @dates;
shift @dates;
shift @dates;
shift @dates;

for my $line (@horiz) {


my @flds = split '\|', $line;
shift @flds;
my $name = shift @flds;
my $event = shift @flds;
my $sub = shift @flds;


my @dates_copy = @dates;
for my $date (@dates_copy) {
print "|$name|$date|$event|$sub|",shift(@flds),"|\n";
}

} # for $line

---------

OUTPUT

---------


|JOHN DOE|01/01/2007|Event1|SUB|PARTY|
|JOHN DOE|01/02/2007|Event1|SUB|CLASS|
|JOHN DOE|01/03/2007|Event1|SUB|WORK|
|JOHN DOE|06/29/2007|Event1|SUB|VACATION|
|JOHN D0E|01/01/2007|Event2|SUB|CLASS|
|JOHN D0E|01/02/2007|Event2|SUB|CLASS|
|JOHN D0E|01/03/2007|Event2|SUB|WORK|
|JOHN D0E|06/29/2007|Event2|SUB|PARTY|
|JANE DOE|01/01/2007|Event1|SUB|PARTY|
|JANE DOE|01/02/2007|Event1|SUB|CLASS|
|JANE DOE|01/03/2007|Event1|SUB|WORK|
|JANE DOE|06/29/2007|Event1|SUB|VACATION|
|JANE DOE|01/01/2007|Event2|SUB|CLASS|
|JANE DOE|01/02/2007|Event2|SUB|CLASS|
|JANE DOE|01/03/2007|Event2|SUB|WORK|
|JANE DOE|06/29/2007|Event2|SUB|PARTY|

But if I make a little change to have the program read the same data from the data file. The last line of output is broken to two lines.

my @horiz = <STDIN>;

my @dates = split '\|', shift @horiz;

shift @dates;
shift @dates;
shift @dates;
shift @dates;


for my $line (@horiz) {

my @flds = split '\|', $line;
shift @flds;
my $name = shift @flds;
my $event = shift @flds;
my $sub = shift @flds;

my @dates_copy = @dates;
for my $date (@dates_copy) {
print "|$name|$date|$event|$sub|",shift(@flds),"|\n";
}

} # for $line

------------
OUTPUT
------------
|JOHN DOE|01/01/2007|Event1|SUB|PARTY|
|JOHN DOE|01/02/2007|Event1|SUB|CLASS|
|JOHN DOE|01/03/2007|Event1|SUB|WORK|
|JOHN DOE|06/29/2007|Event1|SUB|VACATION|
|JOHN DOE|
|Event1|SUB|
|
|JOHN D0E|01/01/2007|Event2|SUB|CLASS|
|JOHN D0E|01/02/2007|Event2|SUB|CLASS|
|JOHN D0E|01/03/2007|Event2|SUB|WORK|
|JOHN D0E|06/29/2007|Event2|SUB|PARTY|
|JOHN D0E|
|Event2|SUB|
|
|JANE DOE|01/01/2007|Event1|SUB|PARTY|
|JANE DOE|01/02/2007|Event1|SUB|CLASS|
|JANE DOE|01/03/2007|Event1|SUB|WORK|
|JANE DOE|06/29/2007|Event1|SUB|VACATION|
|JANE DOE|
|Event1|SUB|
|
|JANE DOE|01/01/2007|Event2|SUB|CLASS|
|JANE DOE|01/02/2007|Event2|SUB|CLASS|
|JANE DOE|01/03/2007|Event2|SUB|WORK|
|JANE DOE|06/29/2007|Event2|SUB|PARTY|
|JANE DOE|
|Event2|SUB||


Can you please advice what the problem is? Thanks.

Replies are listed 'Best First'.
Re: Embeded Data vs Data File
by chromatic (Archbishop) on Jul 18, 2007 at 19:10 UTC

    You split on the newline character with the embedded data, but the newline character is present at the end of your lines when you read from the data file. chomp will fix this:

    my @horiz = <STDIN>; chomp( @horiz ); my @dates = split /\|/, shift @horiz;
Re: Embeded Data vs Data File
by johngg (Canon) on Jul 18, 2007 at 22:13 UTC
    A few minor points.

    You can use splice instead of your multiple shifts. Replace

    shift @dates; shift @dates; shift @dates; shift @dates;

    with

    splice @dates, 0, 4;

    If you are reading a file that is supplied to your script on the command line you can read it by doing <> rather than having to explicitly say <STDIN>

    When reading from the file you might be better off reading a line at a time, especially if the file is large.

    ... my @firstLine = <>; my @dates = split m{\|}, $firstLine; ... while ( my $line = <> ) { ... }

    I hope this is of use,

    Cheers,

    JohnGG