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

Hi Monks!

I need to send a .csv file through POST and one if the string in this .csv file has a "," comma. I've been trying to escape the comma as this,

... my $number = "100"; push @data, [ '1234565', "Prototype", '"Number in address is '.$number.'. Please, Pleas +e check your records."', ];


but when I look at the file it shows two double quotes instead of one as I expected.
1234565,Prototype,""Number in address is 100. Please, check your recor +ds.""


I was aiming for something like this to see if will accept the comma.
1234565,Prototype,"Number in address is 100. Please, check your record +s."
Any suggestions?

Thanks for looking!

Replies are listed 'Best First'.
Re: Creating .csv file with comma
by 1nickt (Canon) on Apr 24, 2020 at 02:30 UTC

    Hi,

    Your values passed to Text::CSV are:

    123456 Prototype "Number in address is 100. Please, check your records."
    ... so Text::CSV escapes the value that has spaces (the default setting) using the default escape character, which is ... a double quote mark.

    But it's only happening because of how you are assembling the value (use sprintf) or because you are trying to quote the comma. Just let Text::CSV handle it:

    $ perl -Mstrict -MText::CSV=csv -wE 'my $num = 100; csv(in => [["12345 +65", "Prototype", "Number in address is $num. Please, Please check yo +ur records.", "foo bar", "baz,qux"]], out => *STDOUT)' 1234565,Prototype,"Number in address is 100. Please, Please check your + records.","foo bar","baz,qux"
    Note 'foo bar' quoted because it contains a space; 'baz,qux' quoted because it contains the field separator character.

    Change the separator character:

    $ perl -Mstrict -MText::CSV=csv -wE 'my $num = 100; csv(in => [["12345 +65", "Prototype", "Number in address is $num. Please, Please check yo +ur records.", "foo bar", "baz,qux"]], out => *STDOUT, sep_char => "|" +)' 1234565|Prototype|"Number in address is 100. Please, Please check your + records."|"foo bar"|baz,qux
    Note 'baz,qux' not quoted because does not contain the separator character, 'but 'foo bar' and your string still quoted because they contain spaces.

    Also turn off quoting of values with spaces:

    $ perl -Mstrict -MText::CSV=csv -wE 'my $num = 100; csv(in => [["12345 +65", "Prototype", "Number in address is $num. Please, Please check yo +ur records.", "foo bar", "baz,qux"]], out => *STDOUT, sep_char => "|" +, quote_space => 0)' 1234565|Prototype|Number in address is 100. Please, Please check your +records.|foo bar|baz,qux
    Note no quoting even where values have spaces (not recommended).

    Hope this helps!


    The way forward always starts with a minimal test.
      This is a sample on how I am formatting the file:
      #!/usr/bin/perl use strict; use warnings; my $number = "100"; my @data; push @data, [ '1234565', "Prototype", '"Number in address is '.$number.'. Please, Please check + your records."', ]; my $csv = Text::CSV->new ( { binary => 1, eol => "\n", quote_char => +'', } ) or die "Cannot use CSV: ".Text::CSV->error_diag (); open my $fh, >, "myfile.csv" or die "Unable to create file: $!"; $csv->print($fh, $_) for @{ $data }; close $fh;

      Thank you!

        Hi again,

        sprintf -- essential tool for avoiding hackery with interpolation and escaping.

        push(@data, [ 1234565, 'Prototype', sprintf('Number in address is %s. Please, Please check your record +s.', $number), ]);
        (I advise always using parens with push and any function that will slurp up whatever's left on the line as args...)

        Hope this helps!


        The way forward always starts with a minimal test.
        I needed to fix the code to make it work and show the issue with double quotes twice.
        #!/usr/bin/perl use strict; use warnings; use Text::CSV; my $number = "100"; my @data = (); push @data, [ '1234565', "Prototype", '"Number in address is '.$number.'. Please, Please check + your records."', ]; my $data = \@data; my $csv = Text::CSV->new ( { binary => 1, eol => "\n", quote_char => +'', } ) or die "Cannot use CSV: ".Text::CSV->error_diag (); open my $fh, ">", "myfile.csv" or die "Unable to create file: $!"; $csv->print($fh, $_) for @{ $data }; close $fh;

        Sorry for that! Thanks!
Re: Creating .csv file with comma
by haukex (Archbishop) on Apr 23, 2020 at 23:04 UTC

    You don't show the code you're actually using to generate the CSV, and it's unclear to me how those quotes are being doubled. If you were to use Text::CSV, which I strongly recommend (also install Text::CSV_XS for speed), you actually don't need to do anything extra: the module will escape characters as necessary. If the escaping is different from what you need, look at the module's options. If you have trouble, post some runnable code with the expected output.

    use Text::CSV; my $csv = Text::CSV->new({binary=>1, auto_diag=>2, eol=>$/}); $csv->print($fh, ['1234565', "Prototype", "Number in address is $number. Please, Please check your records." +]);
      Actually I am using Text::CSV to create the file, that's why the double quotes are been inserted in the file, is there a why to only have one set of quotes instead of two?
        Actually I am using Text::CSV to create the file, that's why the double quotes are been inserted in the file, is there a why to only have one set of quotes instead of two?

        Really? Because if you run the code I showed as-is, the string is surrounded by only one pair of double-quotes, as you want (1234565,Prototype,"Number in address is 100. Please, Please check your records."). And if you add double-quotes to the code I showed, it generates three double quotes in the output, not two, and that's the correct format if your double-quotes are escaped by doubling them. So again, show the code you're using.

        Actually I am using Text::CSV to create the file, that's why the double quotes are been inserted in the file, is there a why to only have one set of quotes instead of two?

        tickle the options :) escape_char

Re: Creating .csv file with comma
by soonix (Chancellor) on Apr 24, 2020 at 05:24 UTC
    Your problem is not the comma, but the quotes. You are using Text::CSV, yet want to do the work yourself. Let Text::CSV do its work instead of introducing that additional pair of quotes. If you entered the data into an Excel sheet, you wouldn't enter additional quotes around text cells with commas either, would you?