Excel 在Perl中读取文件、匹配字符串和格式化输出

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

花了很长时间在这上面,现在我的头都疼了。我已经简化了数据文件,但基本上我已经从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
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