如何使用 Perl 将文本文件解析为 csv 文件
How to parse a text file to csv file using Perl
我正在学习 Perl,想使用 Perl 将文本文件解析为 csv 文件。我有一个生成以下文本文件的循环:
//This part is what outputs on the text file
for $row(@$data) {
while(my($key,$value) = each(%$row)) {
print "${key}=${value}, ";
}
print "\n";
}
文本文件输出:
name=Mary, id=231, age=38, weight=130, height=5.05, speed=26.233, time=30,
time=25, name=Jose, age=30, id=638, weight=150, height=6.05, speed=20.233,
age=40, weight=130, name=Mark, id=369, speed=40.555, height=5.07, time=30
CSV 文件所需输出:
name,age,weight,height,speed,time
Mary,38,130,5.05,26.233,30,
Jose,30,150,6.05,20.233,25,
Mark,40,130,5.04,40.555,30
欢迎任何好的反馈!
这里的关键部分是如何操作您的数据以提取每行需要打印的内容。那么你最好使用模块来生成有效的 CSV,Text::CSV 非常好。
一个程序使用了一个小 hashrefs 数组,模仿了问题中的数据
use strict;
use warnings;
use feature 'say';
use Text::CSV;
my @data = (
{ name => 'A', age => 1, weight => 10 },
{ name => 'B', age => 2, weight => 20 },
);
my $csv = Text::CSV->new({ binary => 1, auto_diag => 2 });
my $outfile = 'test.csv';
open my $ofh, '>', $outfile or die "Can't open $outfile: $!";
# Header, also used below for order of values for fields
my @hdr = qw(name age weight);
$csv->say($ofh, \@hdr);
foreach my $href (@data) {
$csv->say($ofh, [ @{$href}{@hdr} ]);
}
使用 hashref slice @{$href}{@hdr}
提取所需顺序的 hashref 的值,通常是什么
@{ expression returning hash reference } { list of keys }
这 return 是给定键列表的值列表,来自块 {}
中的表达式必须 return 的散列引用。然后用于构建 arrayref(此处为匿名数组,使用 []
),模块的 say
method 需要什么才能制作和打印 comma-separated-values 的字符串† 来自该值列表。
注意计算为散列引用的块,用于代替 散列名称 用于 散列 的一部分.这是一般rule那
Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a BLOCK returning a reference of the correct type.
一些进一步的评论
查看支持的构造函数的属性;有很多好东西
对于非常简单的数据,您可以简单地用逗号连接字段并打印
say $ofh join ',', @{$href}{@hdr};
但是使用模块构建有效的 CSV 记录要安全得多。通过在构造函数中正确选择属性,它可以处理任何合法嵌入字段的内容(其中一些可能需要大量工作才能手动正确完成) 和 它调用事物这不是
我明确列出了列名。相反,您可以按所需顺序获取 keys
,然后获取 sort
,但这将再次需要一个 hard-coded 列表进行排序
程序创建文件 test.csv
并向其打印预期的 header 和数据行。
† 但是用逗号分隔这些“值”可能涉及的不仅仅是“CSV 格式的首字母缩略词“ 代表。这些逗号之间可能有各种各样的东西,包括逗号、换行符等等。这就是为什么最好建议始终使用库的原因。查看构造函数的选项是有用的。
以下评论参考了最初的问题。与此同时,这个解决的问题在 OP 的代码中得到了纠正,问题也得到了更新。我仍将此文本留作一些有用的一般性评论。
至于问题中的代码及其输出,根据 keys[=79 的存在判断,几乎可以肯定数据是如何处理以产生 @data
的问题=] HASH(address)
在输出中。
当打印一个哈希引用变量(不能显示任何哈希内容)时,输出该字符串HASH(0x...)
。 Perl 通过 stringifying 处理这样的打印(从更复杂的东西中生成可打印的字符串)以这种方式引用。
没有充分的理由为散列键提供散列引用。所以我建议你检查你的数据及其处理,看看它是如何产生的。 (或者简要地展示这个,或者 post 如果无法将其添加到这个问题,请提出另一个问题。)
你可以用来绕过的一种方法是只使用你知道有效的密钥列表,就像我上面显示的那样;但是,那么您可能会留下一些未处理的彻底错误。所以我宁愿建议找出问题所在。
我正在学习 Perl,想使用 Perl 将文本文件解析为 csv 文件。我有一个生成以下文本文件的循环:
//This part is what outputs on the text file
for $row(@$data) {
while(my($key,$value) = each(%$row)) {
print "${key}=${value}, ";
}
print "\n";
}
文本文件输出:
name=Mary, id=231, age=38, weight=130, height=5.05, speed=26.233, time=30,
time=25, name=Jose, age=30, id=638, weight=150, height=6.05, speed=20.233,
age=40, weight=130, name=Mark, id=369, speed=40.555, height=5.07, time=30
CSV 文件所需输出:
name,age,weight,height,speed,time
Mary,38,130,5.05,26.233,30,
Jose,30,150,6.05,20.233,25,
Mark,40,130,5.04,40.555,30
欢迎任何好的反馈!
这里的关键部分是如何操作您的数据以提取每行需要打印的内容。那么你最好使用模块来生成有效的 CSV,Text::CSV 非常好。
一个程序使用了一个小 hashrefs 数组,模仿了问题中的数据
use strict;
use warnings;
use feature 'say';
use Text::CSV;
my @data = (
{ name => 'A', age => 1, weight => 10 },
{ name => 'B', age => 2, weight => 20 },
);
my $csv = Text::CSV->new({ binary => 1, auto_diag => 2 });
my $outfile = 'test.csv';
open my $ofh, '>', $outfile or die "Can't open $outfile: $!";
# Header, also used below for order of values for fields
my @hdr = qw(name age weight);
$csv->say($ofh, \@hdr);
foreach my $href (@data) {
$csv->say($ofh, [ @{$href}{@hdr} ]);
}
使用 hashref slice @{$href}{@hdr}
提取所需顺序的 hashref 的值,通常是什么
@{ expression returning hash reference } { list of keys }
这 return 是给定键列表的值列表,来自块 {}
中的表达式必须 return 的散列引用。然后用于构建 arrayref(此处为匿名数组,使用 []
),模块的 say
method 需要什么才能制作和打印 comma-separated-values 的字符串† 来自该值列表。
注意计算为散列引用的块,用于代替 散列名称 用于 散列 的一部分.这是一般rule那
Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a BLOCK returning a reference of the correct type.
一些进一步的评论
查看支持的构造函数的属性;有很多好东西
对于非常简单的数据,您可以简单地用逗号连接字段并打印
say $ofh join ',', @{$href}{@hdr};
但是使用模块构建有效的 CSV 记录要安全得多。通过在构造函数中正确选择属性,它可以处理任何合法嵌入字段的内容(其中一些可能需要大量工作才能手动正确完成) 和 它调用事物这不是
我明确列出了列名。相反,您可以按所需顺序获取
keys
,然后获取sort
,但这将再次需要一个 hard-coded 列表进行排序
程序创建文件 test.csv
并向其打印预期的 header 和数据行。
† 但是用逗号分隔这些“值”可能涉及的不仅仅是“CSV 格式的首字母缩略词“ 代表。这些逗号之间可能有各种各样的东西,包括逗号、换行符等等。这就是为什么最好建议始终使用库的原因。查看构造函数的选项是有用的。
以下评论参考了最初的问题。与此同时,这个解决的问题在 OP 的代码中得到了纠正,问题也得到了更新。我仍将此文本留作一些有用的一般性评论。
至于问题中的代码及其输出,根据 keys[=79 的存在判断,几乎可以肯定数据是如何处理以产生 @data
的问题=] HASH(address)
在输出中。
当打印一个哈希引用变量(不能显示任何哈希内容)时,输出该字符串HASH(0x...)
。 Perl 通过 stringifying 处理这样的打印(从更复杂的东西中生成可打印的字符串)以这种方式引用。
没有充分的理由为散列键提供散列引用。所以我建议你检查你的数据及其处理,看看它是如何产生的。 (或者简要地展示这个,或者 post 如果无法将其添加到这个问题,请提出另一个问题。)
你可以用来绕过的一种方法是只使用你知道有效的密钥列表,就像我上面显示的那样;但是,那么您可能会留下一些未处理的彻底错误。所以我宁愿建议找出问题所在。