使用Perl从输入中提取并过滤一系列行

Ren*_*ené 2 perl foreach

我对Perl很新,我在使用foreach循环跳过行时遇到一些问题.我想将一些文本文件的行复制到一个新行.

当一行的第一个单词时FIRST ITERATION,跳过另外两行并打印所有内容,直到文件结尾或遇到空行.

我试图找到一个类似的帖子,但没有人谈论使用文本文件.

这是我想到的形式

use 5.010;
use strict;
use warnings;

open( INPUT, "xxx.txt" ) or die("Could not open log file.");
open( OUT, ">>yyy.txt" );

foreach my $line (<INPUT>) {

    if ( $line =~ m/^FIRST ITERATION/ ) {

        # print OUT
    }
}

close(OUT);
close(INFO);
Run Code Online (Sandbox Code Playgroud)

我尝试使用next,$line++但我的程序只打印以开头的行FIRST ITERATION.

我可能会尝试使用for循环,但我不知道我的文件可能有多少行,也不知道"第一次迭代"和下一个空行之间有多少行.

Bor*_*din 5

最简单的方法是一次处理一行文件并保留一个状态标志,如果当前行开头则设置为1,如果FIRST ITERATION是空白则保持为0,否则如果它已经为正则它会增加以便它提供当前块中行号的计数

此解决方案期望输入文件的路径作为命令行上的参数并将其输出打印到STDOUT,因此您需要在必要时将输出重定向到命令行上的文件

请注意,正则表达式模式/\S/检查当前行中的任何位置是否存在非空白字符,not /\S/如果该行为空或所有空白字符,则为true

use strict;
use warnings;

my $lines = 0;

while ( <> ) {

    if ( /^FIRST ITERATION/ ) {
        $lines = 1;
    }
    elsif ( not /\S/ ) {
        $lines = 0;
    }
    elsif ( $lines > 0 ) {
        ++$lines;
    }

    print if $lines > 3;
}
Run Code Online (Sandbox Code Playgroud)

这可以通过使用Perl的内置范围操作符来大大简化,该操作符保持其自身的内部状态并返回其评估的次数.所以可以写上面的内容

use strict;
use warnings;

while ( <> ) {
    my $s = /^FIRST ITERATION/ ... not /\S/;
    print if $s and $s > 3;
}
Run Code Online (Sandbox Code Playgroud)

最后一个可以重写为这样的单行命令行程序

$ perl -ne '$s = /^FIRST ITERATION/ ... not /\S/; print if $s and $s > 3' myfile.txt
Run Code Online (Sandbox Code Playgroud)