1

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

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

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

4

3 回答 3

4

这使用 Perl 'autosplit'(或 'awk')模式:

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

参见“ perlrun ”和“ perlvar ”。


如果您需要在给定文件句柄和要跳过的行数的函数中执行此操作,那么您将不会使用 Perl 的“自动拆分”模式。

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;
}
于 2010-11-24T23:53:03.353 回答
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);
于 2010-11-24T23:36:21.860 回答
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__
于 2010-11-25T00:34:50.620 回答