2010-11-24 3 views
1

У меня есть текстовый файл, который выглядит следующим образом:Perl - Начните чтение с определенной линии, и получить только первый столбец строки, до конца

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 

возможно, и если так ли это, где я начать?

+1

Это возможно. У вас еще есть код? – aschepler 2010-11-24 23:34:09

+0

Да и нет. Не для этого еще - но у меня есть еще 300 строк кода, которые я пытаюсь реализовать. Это в основном новая функция, которую я пытаюсь реализовать для обработки файлов из уже существующего текстового файла. – drewrockshard 2010-11-24 23:37:08

+0

Ответ на все вопросы, начинающиеся, * «В Perl, я могу сделать ...?» * ** «Да!» ** Однако ответ на некоторые из них продолжается с ** «Да, но ...». ** – tchrist 2010-11-24 23:55:53

ответ

4

Это использует 'AutoSplit' в Perl режим (или '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

Kinda уродливый, но зачитал фиктивные линии, а затем разделился; для остальных.

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

Это может быть написано примерно так: `my @dummy; @dummy [0..4] = ; map {($ a) = split /; /; print $ a, "\ n"} ; `. – 2010-11-24 23:59:34

2
#!/usr/bin/env perl 
# 
# name_of_program - what the program does as brief one-liner 
# 
# Your Name <[email protected]_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__