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

I need to convert a CSV file to a TAB delimited file using a perl script. I know you can convert from CSV to TAB from the command line using "perl -e ' $sep=","; while(<>) { s/\Q$sep\E/\t/g; print $_; } warn "Changed $sep to tab on $. lines\n" ' csvfile.csv > tabfile.tab", but how do you do this in a perl script? Thank you!

Replies are listed 'Best First'.
Re: Convert CSV file to TAB delimited
by zwon (Abbot) on Sep 22, 2010 at 15:34 UTC

    Something like this:

    use strict; use warnings; use Text::CSV; my $csv = Text::CSV->new( { binary => 1 } ); my $tsv = Text::CSV->new( { binary => 1, sep_char => "\t" } ); open my $infh, '<:utf8', 'input.csv' or die $!; open my $outfh, '>:utf8', 'output.tsv' or die $!; while ( my $row = $csv->getline($infh) ) { $tsv->print( $outfh, $row ); print $outfh "\n"; }

      Small nitpicks, making it even easier:

      • use the eol attribute to prevent the need for extra print calls
      • "<:encoding(utf8)" is much safer than "<:utf8", esp on input
      • use autodie to prevent all kinds of error checking (or add auto_diag => 1)
      use strict; use warnings; use autodie; use Text::CSV; my $csv = Text::CSV->new ({ binary => 1 }); my $tsv = Text::CSV->new ({ binary => 1, sep_char => "\t", eol => "\n" + }); open my $infh, "<:encoding(utf8)", "input.csv"; open my $outfh, ">:encoding(utf8)", "output.tsv"; while (my $row = $csv->getline ($infh)) { $tsv->print ($outfh, $row); }

      otherwise a great reply!


      Enjoy, Have FUN! H.Merijn
Re: Convert CSV file to TAB delimited
by Utilitarian (Vicar) on Sep 22, 2010 at 15:29 UTC
    "perl -e ' $sep=","; while(<>) { s/\Q$sep\E/\t/g; print $_; } warn "Ch +anged $sep to tab on $. lines\n" ' csvfile.csv > tabfile.tab"
    becomes
    #!/usr/bin/perl use strict; use warnings; my $sep=","; open (my $csv_file , "<" , 'csvfile.csv'); open (my $tab_file , ">" , 'tabfile.tab'); while(<$csv_file>) { s/\Q$sep\E/\t/g; print $tab_file, $_; } warn "Changed $sep to tab on $. lines\n"
    However what do you do with lines such as
    "Monster, The Cookie", "123 Sesame St, TV land"
    When processing CSV's there are all kinds of edge cases, so use a module that has looked at these issues already rather than ending up with unsupportable code, I would suggest Text::CSV.

    You can open a new csv object with a different separator and just write it without having to contemplate cases like the above.

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
      Thank you for the code Utilitarian! 'tabfile.tab' is created, but it's empty. I ran the script through debug and when I look at $_, I see the data in tab format. Why is 'tabfile.tab' empty though?

        Because of a small error: one comma too many :)

        while (<$csv_file>) { s/\Q$sep\E/\t/g; print $tab_file, $_; # ^- That comma should not be there }

        Other than that, I still think you ought to look into the proposed Text::CSV_XS or Text::CSV solutions.


        Enjoy, Have FUN! H.Merijn
Re: Convert CSV file to TAB delimited
by locked_user sundialsvc4 (Abbot) on Sep 22, 2010 at 16:42 UTC

    Notice that when you used perl -e ...whatever..., you actually were executing a Perl script, consisting of that one string.

    Most commonly, you build a command-file, written in Perl, that contains what you want to do.

    There are two reasonable ways to do this.   One is to create a file with the extension .pl and execute it with:   perl whatever.pl.

    Another way is, to make a command-file that can be run as an ordinary console command.   You’ll start the file with a “shebang” on the first line, e.g. #!/usr/bin/perl. On a Unix-like system, you use chmod to make the file “executable.”   Now, you can simply run the file, as you would any other command.   The shell will look at the “shebang” line and understand that it is meant for Perl.

    (After so many years, Microsoft is beginning to offer a quasi-decent shell with their systems, which they have rather-amusingly dubbed PowerShell.™   My impression is that it vaguely similar in this regard...)

Re: Convert CSV file to TAB delimited
by Yary (Pilgrim) on Sep 23, 2010 at 01:49 UTC
    All the previous answers are far superior to what I'm about to say, but in the spirit of TMTOWTDI:
    #!/usr/bin/perl -p s/,/\t/g; END{warn "Changed , to tab on $. lines\n"}
    or, for further obfuscation,
    #!/usr/bin/perl -naF, print join "\t",@F; END{warn "Changed , to tab on $. lines\n"}
    perl looks at any switches in the shebang line, which can ease translating one-liners into scripts. It can drive any future maintainers crazy though.
Re: Convert CSV file to TAB delimited
by Anonymous Monk on Nov 06, 2014 at 02:21 UTC

    Here is short script that will print all the .csv formatted files in your current directory, then prompt you for the file to convert and the name to give the tab delimited file. Finally it will perform the conversion

    #!/usr/bin/perl # convert comma seperated file to tab delimited use strict; use warnings; system ("clear"); system ("ls *.csv"); print "\n"; print 'What is the comma seperated file you need to convert? '; chomp (my $csv_file = <> ); print 'What shall I name the new file? '; chomp (my $tabd_file = <> ); system ("< $csv_file tr \",\" \"\t\" > $tabd_file"); exit;
      This doesn't work correctly for commans contained in quotes:
      1,abc,"def,ghi",jkl

      Also, it doesn't work on MS Windows. Calling system for functionality already available in Perl itself isn't needed, anyway. There already are better answers.

      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ