如何强制 Text::CSV 将数字存储为文本?
Posted
技术标签:
【中文标题】如何强制 Text::CSV 将数字存储为文本?【英文标题】:How to force Text::CSV to store number as text? 【发布时间】: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 = $paramsfh;
.. 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);
等)仍然是字符串,除非它暴露于“数字上下文”。您显示的代码都没有这样做,所以您要么从数据库中获取一个数字,要么还有更多的事情发生?
你试过metacpan.org/pod/Text::CSV#keep_meta_info吗?
@zdim,感谢您的回复。我确实在调用$csv->combine
之前直接打印了字段数组的内容,或者更具体地说是$row->code
,并且所有的0 都是正确的。我认为问题出在 Excel 上,这是我用来打开 CSV 文件的工具。如果我在文本编辑器中打开文件,所有的 0 都存在。
您可能知道,有一些方法可以让 Excel 变得如此“有用”。但这可能与本文无关,所以我将在这里发表评论。
【参考方案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)
您可以选择输出中需要多少个前导零,并使所有列的读数相同。
【讨论】:
以上是关于如何强制 Text::CSV 将数字存储为文本?的主要内容,如果未能解决你的问题,请参考以下文章
怎样把excel中所有以文本形式存储的数字转换为数字啊???