【问题标题】:How to force Text::CSV to store number as text?如何强制 Text::CSV 将数字存储为文本?
【发布时间】:2021-06-14 10:10:55
【问题描述】:

我正在编写一些 perl 代码,使用 Text::CSV 模块从数据库中的记录创建一个 .csv 文件。有时,我的表中的一个或多个字段将包含多个重复的 0,这将作为单个 0 写入 CSV。我正在尝试找出如何将数字强制为文本格式,以便所有的 0来自这些领域的内容将保持不变。

    use Text::CSV_XS;

    sub write_file {
       my ($self, %params) = @_;

       my $fh = $params{fh};

       .. do stuff
       .. get database rows

       my $csv = Text::CSV_XS->new({ sep_char => ',' });
    
       for my $row (@$rows) {
           my @fields = (
              $row->{name},
              $row->{address},
              $row->{code}
           );

           $csv->combine(@fields);

           print $fh $csv->string . "\r\n"
               or die 'Write error.';
       }

使用这种方法,大部分时间一切看起来都很好。但是,当代码以“00000”的形式出现时,它会被截断并在我的 CSV 中写为“0”。

我调查了$csv->types,但这仅允许在解析期间解码时定义类型。

我还尝试使用 $csv->quote(@fields) 将字段括在引号中,但没有成功。

【问题讨论】:

  • "code 作为 "00000"" --- 你在什么时候可以确认它仍然是一个字符串00(让我们保持两个零) ?如果您打印 $row->{code} 是多个零吗?我在重现问题时遇到了麻烦:如果我用 q(00)(带引号的)字符串组成一个 hashref 并做你展示的其余部分 - 并且不要做任何类似数字的东西它——它在 CSV 文件中以00 结尾。
  • 换句话说,以字符串开头的内容(my $s = q(00); 等)仍然是字符串,除非它暴露于“数字上下文”。您显示的代码都没有这样做,所以您要么从数据库中获取一个数字,要么还有更多的事情发生?
  • @zdim,感谢您的回复。我确实在调用$csv->combine 之前直接打印了字段数组的内容,或者更具体地说是$row->{code},并且所有的0 都是正确的。我认为问题出在 Excel 上,这是我用来打开 CSV 文件的工具。如果我在文本编辑器中打开文件,所有的 0 都存在。
  • 您可能知道,有一些方法可以让 Excel 变得如此“有用”。但这可能与本文无关,所以我将在这里发表评论。

标签: string csv perl formatting truncate


【解决方案1】:

参考always_quote() 强制合并的字段被引用

use Text::CSV_XS;
my $csv = Text::CSV_XS->new( { sep_char => ',' } );

my @fields = ( "0", "00", "000" );

$csv->combine(@fields);
print $csv->string . "\n";

$csv->always_quote(1);
$csv->combine(@fields);
print $csv->string . "\n";

导致

0,00,000
"0","00","000"

【讨论】:

  • 我认为 @ComputersAreNeat 是在询问如何让报价显示出来,但阅读上面的 cmets 可能表明他们真的在询问如何让 Excel 进行投标。
  • Excel 默认将所有三个带引号的零转换为 0
  • 重读该评论表明他们意识到“问题在于 Excel”
【解决方案2】:

规范化您的数据

如果问题是这样的

  • 你想要前导 0,
  • 输入中的前导零重要(即科学记数法)

然后你可以简单地用sprintf规范化数据

$x = 5;
print sprintf("%05d", $x)

您可以选择输出中需要多少个前导零,并使所有列的读数相同。

【讨论】:

    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 2015-10-08
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    相关资源
    最近更新 更多