代码之家  ›  专栏  ›  技术社区  ›  drewrockshard

Perl—从特定行开始读取,只获取该行的第一列,直到结束

  •  1
  • drewrockshard  · 技术社区  · 14 年前

    我有一个文本文件,如下所示:

    Line 1
    Line 2
    Line 3
    Line 4
    Line 5
    filename2.tif;Smpl/Pix & Bits/Smpl are missing.
    

    有5行总是一样的,第6行是我想开始读取数据的地方。读取数据时,每行(从第6行开始)用分号分隔。我只需要得到每一行的第一个条目(从第6行开始)。

    例如:

    Line 1
    Line 2
    Line 3
    Line 4
    Line 5
    filename2.tif;Smpl/Pix & Bits/Smpl are missing.
    filename4.tif;Smpl/Pix & Bits/Smpl are missing.
    filename6.tif;Smpl/Pix & Bits/Smpl are missing.
    filename8.tif;Smpl/Pix & Bits/Smpl are missing.  
    

    所需输出为:

    filename2.tif
    filename4.tif
    filename6.tif
    filename8.tif
    

    这可能吗?如果可能,我从哪里开始?

    3 回复  |  直到 14 年前
        1
  •  4
  •   Jonathan Leffler    14 年前

    它使用Perl“autosplit”(或“awk”)模式:

    perl -n -F'/;/' -a -e 'next if $. <= 5; print "$F[0]\n";' < data.file
    

    perlrun '和' perlvar '.


    如果您需要在一个给定了文件句柄和许多要跳过的行的函数中执行此操作,那么您将不会使用Perl的“autosplit”模式。

    sub skip_N_lines_read_column_1
    {
        my($fh, $N) = @_;
        my $i = 0;
        my @files = ();
        while (my $line = <$fh>)
        {
            next if $i++ < $N;
            my($file) = split /;/, $line;
            push @files, $file;
        }
        return @files;
    }
    

    这将初始化一个循环,读取行,跳过前N行,然后分割行并仅捕获第一个结果。那句台词 my($file) = split... 很微妙;括号表示拆分有一个列表上下文,因此它生成一个值列表(而不是一个值计数)并将第一个值赋给变量。如果省略了括号,您将为列表运算符提供标量上下文,这样您将获得分配给的拆分输出中的字段数 $file -不是你需要的。文件名追加到数组的末尾,然后返回数组。因为代码没有打开文件句柄,所以它不会关闭它。另一个接口会将文件名(而不是打开的文件句柄)传递到函数中。然后在函数中打开和关闭文件,担心错误处理。

    如果你需要帮助打开文件等,那么:

    use Carp;
    
    sub open_skip_read
    {
        my($name) = @_;
        open my $fh, '<', $name or croak "Failed to open file $name ($!)";
        my @list = skip_N_lines_read_column_1($fh, 5);
        close $fh or croak "Failed to close file $name ($!)";
        return @list;
    }
    
        2
  •  2
  •   tchrist    14 年前
    #!/usr/bin/env perl
    #
    # name_of_program - what the program does as brief one-liner
    #
    # Your Name <your_email@your_host.TLA>
    # Date program written/released
    #################################################################
    
    use 5.10.0;
    
    use utf8;
    use strict;
    use autodie;
    use warnings FATAL => "all";
    
    #  ⚠ change to agree with your input: ↓
    use open ":std" => IN    => ":encoding(ISO-8859-1)",
                       OUT   => ":utf8";
    #  ⚠ change for your output: ↑ — *maybe*, but leaving as UTF-8 is sometimes better
    
    END {close STDOUT}
    
    our $VERSION = 1.0;
    
    $| = 1;
    
    if (@ARGV == 0 && -t STDIN) {
       warn "reading stdin from keyboard for want of file args or pipe";
    }
    
    while (<>) {
        next if 1 .. 5;
        my $initial_field = /^([^;]+)/ ? $1 : next;
        #    ╔═══════════════════════════╗
        #   ☞ your processing goes here ☜
        #    ╚═══════════════════════════╝
    } continue {
        close ARGV if eof;
    }
    
    __END__
    
        3
  •  2
  •   dmah    14 年前

    有点难看,但是,读出虚线,然后分开,剩下的。

    my $logfile = '/path/to/logfile.txt';
    
    open(FILE, $logfile) || die "Couldn't open $logfile: $!\n";
    
    for (my $i = 0 ; $i < 5 ; $i++) {
       my $dummy = <FILE>;
    }
    
    while (<FILE>) {
       my (@fields) = split /;/;
       print $fields[0], "\n";
    }
    
    close(FILE);