Excel 在Perl中读取文件、匹配字符串和格式化输出
花了很长时间在这上面,现在我的头都疼了。我已经简化了数据文件,但基本上我已经从5个不同的文件中提取了一些值,现在我想将它们绘制到excel中。因此,excel中直线图的格式需要更正 当前文件看起来像Excel 在Perl中读取文件、匹配字符串和格式化输出,excel,perl,csv,Excel,Perl,Csv,花了很长时间在这上面,现在我的头都疼了。我已经简化了数据文件,但基本上我已经从5个不同的文件中提取了一些值,现在我想将它们绘制到excel中。因此,excel中直线图的格式需要更正 当前文件看起来像 Report-20140521.csv: Sun, 20 Report-20140530.csv: Sun, 23 Report-20140606.csv: Sun, 24 Report-20140613.csv: Sun, 25 Report-20140621.csv: Sun, 21 Repor
Report-20140521.csv: Sun, 20
Report-20140530.csv: Sun, 23
Report-20140606.csv: Sun, 24
Report-20140613.csv: Sun, 25
Report-20140621.csv: Sun, 21
Report-20140521.csv: Mon, 22
Report-20140530.csv: Mon, 23
Report-20140606.csv: Mon, 24
Report-20140613.csv: Mon, 24
Report-20140621.csv: Mon, 21
Report-20140521.csv: Tues, 22
Report-20140530.csv: Tues, 23
Report-20140606.csv: Tues, 20
Report-20140613.csv: Tues, 21
Report-20140621.csv: Tues, 21
我想把这些都展平,有五行,每行都有值,如:-
Sun Mon Tue wed ..
Report-20140521.csv: 20 22 22
Report-20140530.csv: 23 23 23
Report-20140606.csv: 24 24 20
Report-20140613.csv: 25 24 21
Report-20140621.csv: 21 21 21
我们已经研究过使用数组和数组数组,但无论哪种方式,数据似乎都被篡改了,无法使用5条不同的线将其展平。除此之外,我还需要保留文件名,因为它将在以后的excel中分条为日期格式。我认为散列可以很好地解决这个问题,因为您的星期日值是离散的和有界的。这种方法的某些变体可能会起作用:
use strict;
my %matrix;
open IN, 'yourfile.txt' or die $!;
while (<IN>) {
chomp;
my ($report, $val) = split /,/;
my ($file, $dow) = split /: /, $report;
$matrix{$file}{$dow} = $val;
}
close IN;
my @dow = qw(Sun Mon Tues Wed Thu Fri Sat);
foreach my $file (sort keys %matrix) {
print $file, "\t";
my $report_ref = $matrix{$file};
foreach my $dow (@dow) {
print $$report_ref{$dow}, "\t";
}
print "\n";
}
您可以使用数组散列来存储数据,然后打印出与列名匹配的值(即日期):
此解决方案按您的要求执行。它使用散列
%headers
在读取数据时将日期名称转换为列号,并生成由CSV文件名键入的散列。散列的值是值对的数组,每对值由一个列号和该列的一个值组成
一旦数据被分解成散列,就会按照文件名的顺序进行扫描。数组@info
初始化为七个空字段,散列中的列/值对用于覆盖提供的列
文件名的最大长度是确定的,首先用于打印日期名的@headers
数组,然后用于打印每个哈希项的@info
数组
我希望这有帮助
use strict;
use warnings;
use List::Util 'max';
my $filename = 'current.txt';
open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!};
my @headers = qw/ Sun Mon Tue Wed Thu Fri Sat /;
my %headers = map { $headers[$_] => $_ } 0 .. $#headers;
my %file_data;
while (<$fh>) {
next unless my @fields = /(\S[^:]+:)\s+(\w{3})\w*, (\d+)/;
my $file = shift @fields;
$fields[0] = $headers{ucfirst lc $fields[0]};
push @{ $file_data{$file} }, \@fields;
}
my $width = max map length, keys %file_data;
my $format = "%*s%3s %3s %3s %3s %3s %3s %3s\n";
printf $format, $width, '', @headers;
for my $file (sort keys %file_data) {
my $days = $file_data{$file};
my @info = ('') x 7;
for my $day (@$days) {
my ($index, $val) = @$day;
$info[$index] = $val;
}
printf $format, $width, $file, @info;
}
旁注:在
警告下投诉
<代码>打开我的$IN,@mpapec——我已经离开Perl好几年了,但是我注意到最近所有的代码片段都使用了“打开我的$IN”而不是你建议的“打开IN”。这是方法学上的最新变化,还是我一直在做错事?这不是“错”,但它带来了一些含义,即typeglob应该本地化localin
在open
之前,因为它具有全局性,因此可能会发生冲突。Perl5版本6于2000年3月引入了此功能,以及open
的三参数形式。这似乎花了很长时间才流行起来,但现在认为两者都使用是最佳实践。看看perldelta,非常感谢您的回答,看起来很不错,明天我们会仔细看看。感谢你的时间和努力。那么“wed…”呢?非常感谢你的回答看起来很棒,明天我们会仔细看看。感谢你的时间和努力。非常感谢这个答案看起来很棒,明天我们会仔细看看。感谢你的时间和努力。
use warnings;
use strict;
open my $in, '<', 'in.txt';
my (%data, @record, @day, @n);
while (<$in>){
chomp;
my @split = split(/\s/);
push @record, $split[0];
$split[1] =~ s/,//g;
push @day, $split[1];
push @n, $split[2];
}
push @{$data{$record[$_]} }, [ $day[$_], $n[$_] ] for 0 .. $#record;
my @days = qw(Sun Mon Tues Wed Thu Fri Sat);
print "$_ " foreach (@days);
print "\n";
for my $report (sort keys %data){
print "$report\t";
for my $val (@{$data{$report}}){
my ($day, $n) = @$val;
foreach(@days){
print "$n\t" if $day eq $_;
}
print "\n";
}
}
Sun Mon Tues Wed Thu Fri Sat
Report-20140521.csv: 20 22 22
Report-20140530.csv: 23 23 23
Report-20140606.csv: 24 24 20
Report-20140613.csv: 25 24 21
Report-20140621.csv: 21 21 21
use strict;
use warnings;
use List::Util 'max';
my $filename = 'current.txt';
open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!};
my @headers = qw/ Sun Mon Tue Wed Thu Fri Sat /;
my %headers = map { $headers[$_] => $_ } 0 .. $#headers;
my %file_data;
while (<$fh>) {
next unless my @fields = /(\S[^:]+:)\s+(\w{3})\w*, (\d+)/;
my $file = shift @fields;
$fields[0] = $headers{ucfirst lc $fields[0]};
push @{ $file_data{$file} }, \@fields;
}
my $width = max map length, keys %file_data;
my $format = "%*s%3s %3s %3s %3s %3s %3s %3s\n";
printf $format, $width, '', @headers;
for my $file (sort keys %file_data) {
my $days = $file_data{$file};
my @info = ('') x 7;
for my $day (@$days) {
my ($index, $val) = @$day;
$info[$index] = $val;
}
printf $format, $width, $file, @info;
}
Sun Mon Tue Wed Thu Fri Sat
Report-20140521.csv: 20 22 22
Report-20140530.csv: 23 23 23
Report-20140606.csv: 24 24 20
Report-20140613.csv: 25 24 21
Report-20140621.csv: 21 21 21