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

时间:2010-11-24 23:28:14

标签: regex perl filehandle

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

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 个答案:

答案 0 :(得分:4)

这使用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;
}

答案 1 :(得分:2)

有点难看但是,读出虚线然后分开;对于其他人。

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);

答案 2 :(得分:2)

#!/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__