0

I am trying to understand an error with a PERL program. I have a comma-separated file, and I want to extract the contents of each row to a separate text file, using the contents of the first field in each row as the file name.

The program below does exactly this EXCEPT it skips the first line of the csv file. I tried to nail down the source of the error by adding a couple of print commands. The print command on line 22 shows that the first line is read by the command in line 21. But, once the foreach loop starts, the first line is not printed.

I'm not quite sure of the problem. I appreciate any help!

#!/usr/bin/perl
# script that takes a .csv file (such as that exported from Excel) and 
# extracts the contents of each row into a separate text file, using the first column as the filename
# original source: http://www.tek-tips.com/viewthread.cfm?qid=1516940
# modified 3/14/12
# usage = ./export_rows.pl <yourfilename>.csv

use warnings;
use strict;
use Text::CSV_XS;
use Tie::Handle::CSV;

unless(@ARGV) {
    print "Please supply a .csv file at the command line! For example, export_rows.pl myfile.csv\n";
    exit;
}

my $fh = Tie::Handle::CSV->new(file => $ARGV[0],
                           header => 0);

my @headers = @{scalar <$fh>};
print "$headers[0]\n\n";

foreach my $csv_line (<$fh>) {
    print "$csv_line->[0]\n";
    open OUT, "> $csv_line->[0].txt" or die "Could not open file $csv_line->[0].txt for output.\n$!";
    for my $i (1..$#headers) {
         print OUT "$csv_line->[$i]\n";
    }
    close OUT;
 }

 close $fh;
2
  • 2
    my guess is you need to start at 0 in your for loop. Commented Aug 23, 2012 at 20:32
  • @squiguy make that an answer, so we can give you upvotes. Commented Aug 23, 2012 at 20:35

1 Answer 1

5

Try beginning at 0 in your for loop:

for my $i (1..$#headers)

Should be:

for my $i (0..$#headers)

EDIT:

To get the first line of the file you can use Tie::File

Here is sample code:

my @arr;
tie @arr, 'Tie::File', 'a.txt' or die $!;
my $first = $arr[0];
untie @arr;

print "$first\n";

This module is cool in that it allow you to access lines of a file via accessing indices in an array. If your file is big it is not incredibly efficient, but I think you can definitely use it here.

Sign up to request clarification or add additional context in comments.

4 Comments

This line controls which fields in the row are printed to the output file. I want to use the first field as part of the filename and then extract the remaining fields, so that line is correct as is. I think the first line problem is occurring between the @headers initialization and the foreach loop.
@user1620933 I believe the line before the print loop with the diamond operator advances the first line so it will get skipped the next time you read from it. Which is the foreach loop.
That seems consistent with the behavior I've observed. Unfortunately, I don't know how to fix this. I tried a seek command to "reset" the file, but that doesn't work. Any suggestions on how to get the foreach loop to start at the beginning of the file?
@user1620933 I update my answer. Let me know if you need help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.