0

perl で、前および/または次の行から情報を保持するための最良/正しい方法は何ですか? たとえば、次のコードを使用します。

while (<IN>) {
   print;
}

ファイルの前または次の行が foo に一致する場合にのみ行を印刷せず、それ以外の場合は印刷するように変更するにはどうすればよいですか?

コード例を教えてください。ありがとう。

4

4 に答える 4

2

行を配列に読み込むことができます。その後、何らかの方法でシグナルを受け取るものがあれば、配列の最後のいくつかの要素をポップアウトします。すべてを読み終えたら、それを印刷できます。

use strict;
use warnings;
use feature qw(say);
use autodie;  #Won't catch attempt to read from an empty file

use constant    FILE_NAME => "some_name.txt"
   or die qq(Cannot open ) . FILE_NAME . qq(for reading: $!\n);
open my $fh, "<", FILE_NAME;

my @output;
LINE:
while ( my $line = <DATA> ) {
    chomp $line;
    if ( $line eq "foo" ) {
        pop @output;  #The line before foo
        <DATA>;        #The line after foo
        next LINE;    #Skip line foo. Don't push it into the array
    }
    push @output, $line;
}

そこから、印刷したくない値を既に処理して配列を印刷できます。

for my $line ( @output ) {
   say $line;
}

唯一の問題は、これがメモリを消費することです。ファイルが非常に大きい場合、メモリ不足になる可能性があります。

これを回避する 1 つの方法は、bufferを使用することです。値を配列に格納し、配列に別の値をプッシュするときに最後の値をシフトアウトします。読み込まれた値が の場合foo、配列をリセットできます。この場合、バッファーには最大で 1 行が含まれます。

#! /usr/bin/env perl

use strict;
use warnings;
use autodie;
use feature qw(say);

my @buffer;
LINE:
while ( my $line = <DATA> ) {
    chomp $line;
    if ( $line eq "foo" ) {
        @buffer = ();    #Empty buffer of previous line
        <DATA>;           #Get rid of the next line
        next LINE;       #Foo doesn't get pushed into the buffer
    }
    push @buffer, $line;
    if ( @buffer > 1 ) {    #Buffer is "full"
        say shift @buffer; #Print out previous line
    }
}
#
# Empty out buffer
#
for my $line ( @buffer ) {
    say $line;
}
__DATA__
2
3
4
5
6
7
8
9
10
11
12
13
1
2
foo
3
4
5
foo
6
7
8
9
foo

次の行をスキップすると、空のファイルから読み取ろうとする可能性が非常に高いことに注意してください。これは大丈夫です。は<$fh>空の文字列または undef を返しますが、それは無視できます。ループの先頭に戻ると、エラーが発生します。

于 2013-08-19T03:12:29.333 に答える