【问题标题】:perl + read multiple csv files + manipulate files + provide output_filesperl + 读取多个 csv 文件 + 操作文件 + 提供 output_files
【发布时间】:2014-03-18 23:42:36
【问题描述】:

抱歉,如果这有点啰嗦,但我真的很感谢这里的答案,因为我很难让它工作。

基于这个问题here,我有这个脚本可以在 csv 文件 (orig.csv) 上运行并提供我想要的 csv 文件 (format.csv)。我想要的是使它更通用并接受任意数量的“.csv”文件,并为每个输入的文件提供一个“输出_csv”。有人可以帮忙吗?

 #!/usr/bin/perl

    use strict;
    use warnings;

    open my $orig_fh,   '<', 'orig.csv'   or die $!;
    open my $format_fh, '>', 'format.csv' or die $!;

    print $format_fh scalar <$orig_fh>; # Copy header line

    my %data;
    my @labels;

    while (<$orig_fh>) {
      chomp;
      my @fields = split /,/, $_, -1;
      my ($label, $max_val) = @fields[1,12];
      if ( exists $data{$label} ) {
        my $prev_max_val = $data{$label}[12] || 0;
        $data{$label} = \@fields if $max_val and $max_val > $prev_max_val;
      }
      else {
        $data{$label} = \@fields;
        push @labels, $label;
      }
    }

    for my $label (@labels) {
      print $format_fh join(',', @{ $data{$label} }), "\n";
    }

我希望使用来自here 的这个脚本,但我很难将两者放在一起:

#!/usr/bin/perl
    use strict;
    use warnings;
    #If you want to open a new output file for every input file
    #Do it in your loop, not here.
    #my $outfile = "KAC.pdb";
    #open( my $fh, '>>', $outfile );
    opendir( DIR, "/data/tmp" ) or die "$!";
    my @files = readdir(DIR);
    closedir DIR;
    foreach my $file (@files) {
    open( FH, "/data/tmp/$file" ) or die "$!";
    my $outfile = "output_$file"; #Add a prefix (anything, doesn't have to say 'output')
    open(my $fh, '>', $outfile);
    while (<FH>) {
    my ($line) = $_;
    chomp($line);
    if ( $line =~ m/KAC 50/ ) {
    print $fh $_;
    }
    }
    close($fh);
    }

脚本读取目录中的所有文件并找到包含此字符串“KAC 50”的行,然后将该行附加到output_$fileinputfile。所以每读取一个inputfile,就会有1个output_$file

我已经注意到并希望修复的此脚本的问题: - 它读作“。”和 '..' 目录中的文件并生成一个 '输出_。'和“输出_..”文件 - 它也会对这个脚本文件做同样的事情。

我还试图通过添加此代码使此脚本在运行它的任何目录中工作来使其动态化:

use Cwd qw();
my $path = Cwd::cwd();
print "$path\n";

opendir( DIR, $path ) or die "$!";  # open the current directory 
open( FH, "$path/$file" ) or die "$!"; #open the file

**EDIT::我已尝试合并版本,但出现错误。非常感谢您的建议*

UserName@wabcl13 ~/Perl
$ perl formatfile_QforStackOverflow.pl
Parentheses missing around "my" list at formatfile_QforStackOverflow.pl line 13.
source dir -> /home/UserName/Perl
Can't use string ("/home/UserName/Perl/format_or"...) as a symbol ref while "strict refs" in use at formatfile_QforStackOverflow.pl line 28.

组合码::

  use strict;
    use warnings;
    use autodie;   # this is used for the multiple files part...

    #START::Getting current working directory 
    use Cwd qw();
    my $source_dir = Cwd::cwd();
    #END::Getting current working directory 

    print "source dir -> $source_dir\n";
    my $output_prefix = 'format_';

    opendir my $dh, $source_dir; #Changing this to work on current directory; changing back

    for my $file (readdir($dh)) {
        next if $file !~ /\.csv$/;
        next if $file =~ /^\Q$output_prefix\E/;

        my $orig_file = "$source_dir/$file";
        my $format_file = "$source_dir/$output_prefix$file";

        # .... old processing code here ...
        ## Start:: This part works on one file edited for this script ##
        #open my $orig_fh,   '<', 'orig.csv'   or die $!; #line 14 and 15 above already do this!!
        #open my $format_fh, '>', 'format.csv' or die $!;

        #print $format_fh scalar <$orig_fh>; # Copy header line #orig needs changeing
        print $format_file  scalar <$orig_file>; # Copy header line

        my %data;
        my @labels;

        #while (<$orig_fh>) { #orig needs changing
        while (<$orig_file>) {
          chomp;
          my @fields = split /,/, $_, -1;
          my ($label, $max_val) = @fields[1,12];
          if ( exists $data{$label} ) {
            my $prev_max_val = $data{$label}[12] || 0;
            $data{$label} = \@fields if $max_val and $max_val > $prev_max_val;
          }
          else {
            $data{$label} = \@fields;
            push @labels, $label;
          }
        }

        for my $label (@labels) {
          #print $format_fh join(',', @{ $data{$label} }), "\n";  #orig needs changing
          print $format_file join(',', @{ $data{$label} }), "\n";
        }
        ## END:: This part works on one file edited for this script ##

    }

【问题讨论】:

    标签: perl csv


    【解决方案1】:

    您打算如何输入要处理的文件列表及其首选输出目的地?也许只是有一个固定的目录,你想处理所有的 cvs 文件,并为结果加上前缀。

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use autodie;
    
    my $source_dir = '/some/dir/with/cvs/files';
    my $output_prefix = 'format_';
    
    opendir my $dh, $source_dir;
    for my $file (readdir($dh)) {
        next if $file !~ /\.csv$/;
        next if $file =~ /^\Q$output_prefix\E/;
    
        my $orig_file = "$source_dir/$file";
        my $format_file = "$source_dir/$output_prefix$file";
    
        .... old processing code here ...
    
    }
    

    或者,您可以只使用一个输出目录而不是为文件添加前缀。无论哪种方式,这都应该让您顺利上路。

    【讨论】:

    • 抱歉,这很清楚,我只是将格式化的文件保存在同一目录中,但它们会有一个前缀来区分。这是一个好习惯吗? tks
    • 这是一个很好的实践,只要你正确地编码。我向您展示的内容将完成大部分工作。不过,您最终将需要学习更多的编码技能,而不仅仅是将其他人在论坛上提供的代码放在一起。祝你好运。
    • 仍有错误,感谢您的建议,编辑了我的 Q,tks
    • @HattrickNZ 如果您遇到语法错误,您应该首先专注于理解和修复它们。这些错误通常会告诉您它们发生的确切行号。如果您需要帮助理解特定的错误消息,那么请务必发布您的代码并提出特定问题。但我希望听到您首先尝试自己找出错误消息所做的工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 2015-05-23
    相关资源
    最近更新 更多