【问题标题】:File manipulation in PerlPerl 中的文件操作
【发布时间】:2011-09-14 14:03:05
【问题描述】:

我有一个简单的 .csv 文件,我想从写入新文件中提取数据。

我要编写一个读取文件的脚本,读取每一行,然后以不同的顺序拆分和构造列,如果 .csv 中的行包含“xxx” - 不要将该行输出到输出文件。

我已经设法读入一个文件,并创建了一个辅助文件,但是我是 Perl 的新手,并且仍在尝试制定命令,以下是我编写的用于掌握 Perl 并想知道的测试脚本如果我能把它改成我需要的?-

open (FILE, "c1.csv") || die "couldn't open the file!";
open (F1, ">c2.csv") || die "couldn't open the file!";

#print "start\n";

sub trim($);

sub trim($)
{
    my $string = shift;
    $string =~ s/^\s+//;
    $string =~ s/\s+$//;
    return $string;
}

$a = 0;
$b = 0;
while ($line=<FILE>)
{
    chop($line);

    if ($line =~ /xxx/)
    {
        $addr = $line;
        $post = substr($line, length($line)-18,8);
    }
    $a = $a + 1;
}

print $b;
print " end\n";

非常感谢任何帮助。

【问题讨论】:

  • 我想我会给你一些风格指针,希望你不介意。 0. 将use strict;use warnings; 放在所有脚本的顶部。您必须使用my 声明变量,但从长远来看,它会节省您的调试时间——例如my $foo = bar(); 1. 在 perl 中,无需预先声明您的子例程——在十多年的大量 Perl 使用中,我从来没有需要这个功能。 2. 一般来说,不要在你的潜艇上使用原型,它们不像在其他语言中那样工作。它们只是编译器提示,可以轻松绕过。
  • 更多样式指针。 3.变量$a$bsort使用的特殊变量。最好不要在其他任何地方使用它们。如果您确保它们是词法范围的,那可能是安全的,但是,一般来说,我会避免使用它们。 4.像FILE这样的文件句柄是全局变量,最好用词法句柄代替。 5. Open 有 3 参数形式和 2 参数形式。保留 2 参数版本是为了向后兼容,但它有一些问题。请改用 3 arg 形式。现代 3-arg 词法打开示例:open my $fh, '&gt;', $path_to_some_file or die "Didn't work: $!\n";.
  • 您的代码中的大多数问题都是过时或令人困惑的文档问题。幸运的是,有更多当前 Perl 使用的来源可用。 brian d foy 的 Effective Perl Programming 和 chromatic 的 Modern Perl 是几本优秀的书籍。 Modern Perl 甚至可以免费下载:onyxneon.com/books/modern_perl/index.html

标签: perl csv text


【解决方案1】:

要操作 CSV 文件,最好使用 CPAN 中的可用模块之一。我喜欢Text::CSV

use Text::CSV;

my $csv = Text::CSV->new ({ binary => 1, empty_is_undef => 1 }) or die "Cannot use CSV: ".Text::CSV->error_diag ();

open my $fh, "<", 'c1.csv' or die "ERROR: $!";
$csv->column_names('field1', 'field2');
while ( my $l = $csv->getline_hr($fh)) {
    next if ($l->{'field1'} =~ /xxx/);
    printf "Field1: %s Field2: %s\n", $l->{'field1'}, $l->{'field2'}
}
close $fh;

【讨论】:

  • 感谢您的输入,但它会显示错误“无法在 @INC
  • 我完全同意 PacoRG; Text::CSV 是正确的方法。
  • Lambo:您需要先安装Text::CSV 模块。尝试按照此处的说明从 PPM 安装它:docs.activestate.com/activeperl/5.10/faq/ActivePerl-faq2.html
  • 啊,我知道我错过了!感谢您安装它。
  • 如果您的系统上没有安装 Text::CSV 并且您没有时间安装它,那么另一种方法是使用 Text::ParseWords 模块,该模块是作为标准 Perl 安装,因此已经安装。
【解决方案2】:

如果你只需要一次,所以以后不需要程序你可以用oneliner来做:

perl -F, -lane 'next if /xxx/; @n=map { s/(^\s*|\s*$)//g;$_ } @F; print join(",", (map{$n[$_]} qw(2 0 1)));'

细分:

perl -F, -lane
     ^^^   ^ <- split lines at ',' and store fields into array @F

next if /xxx/;    #skip lines what contain xxx

@n=map { s/(^\s*|\s*$)//g;$_ } @F;
    #trim spaces from the beginning and end of each field
    #and store the result into new array @n

print join(",", (map{$n[$_]} qw(2 0 1)));
    #recombine array @n into new order - here 2 0 1
    #join them with comma
    #print

当然,对于重复使用,或者在更大的项目中,您应该使用一些 CPAN 模块。而且上面的oneliner也有很多注意事项。

【讨论】:

    猜你喜欢
    • 2012-05-29
    • 2015-05-31
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    相关资源
    最近更新 更多