Perl的.使用直到功能

ES5*_*S55 5 arrays perl loops compare conditional-statements

我有一个简单的数据文件.文件中的每一行都有四个元素.有些行没有空白条目.其他行有第一个条目,其余三个是空白的,或者更确切地说是"填充"了一个空格.它是制表符分隔文件.

输入文件的示例:

    .
    .
    .
    30  13387412    34.80391242 sSN_FIRST
    30  13387412    34.80391242 sSN5_40
    30.1             
    30.2             
    30.3             
    30.4             
    31  14740248    65.60590089 s32138223_44
    31  14740248    65.60590089 s321382_LAST
    .
    .
    .
Run Code Online (Sandbox Code Playgroud)

重申一下,如果这很重要,我文件中的"空白"实际上包含一个空格.

我的总体目标是在整个文件中"填写"第二和第三列(第四列被忽略).为了做到这一点,我需要我的脚本来识别空白的连续行的集合,加上紧接在前面的行和紧接在连续空行集合之后的行.在上面的例子中,这将是第2-7行.一旦我能够这样做,我可以使用填充的侧翼线中的信息来帮助"填写"两者之间的线中缺失的条目.

我一直在试验这个until函数,但是我没有成功地将它与一个读取数据行的循环耦合.例如,我可以读取行并找到空行:

open( my $FILE, "<$mapfile" );
my @file = <$FILE>;
close $FILE;

for ( my $i = 1 ; $i < scalar @file ; $i++ ) 
    {
     my @entries = split( '\t', $file[ $i ] );
     if ( $entries[ 1 ] =~ m/ / ) 
        {
         print $file[ $i ]."\n";
        }
    }
Run Code Online (Sandbox Code Playgroud)

但我正在尝试使用该until函数,以便读取行并搜索我正在寻找的连续行集("空白"行加上两个侧面"完整"行).例如:

until ( $file[ a line ] =~ m/ / && $file[ another line ] =~ m/ / )   
    {
     my linear interpolation here;
    }
Run Code Online (Sandbox Code Playgroud)

任何人都可以给我一个关于如何结合读取数组和比较线以找到我需要的整个文件集的提示吗?

Ken*_*sis 2

也许以下内容会有所帮助:

use strict;
use warnings;

my ( $last, $oneColumn );

my @file = <DATA>;

for my $line (@file) {
    my @entires = split ' ', $line;

    if ( @entires == 4 ) {
        if ($oneColumn) {
            print $line;    # Succeeding line
            $oneColumn = 0;
        }
        $last = $line;
        next;
    }

    print $last if $last;    # Preceeding line
    undef $last;
    print $line;             # One-column line
    $oneColumn = 1;

}

__DATA__
30  13387412    34.80391242 sSN_FIRST
30  13387412    34.80391242 sSN5_40
30.1             
30.2             
30.3             
30.4             
31  14740248    65.60590089 s32138223_44
31  14740248    65.60590089 s321382_LAST
Run Code Online (Sandbox Code Playgroud)

输出:

30  13387412    34.80391242 sSN5_40
30.1
30.2
30.3
30.4
31  14740248    65.60590089 s32138223_44
Run Code Online (Sandbox Code Playgroud)

一条“完整”行应该在 中包含四个元素@entries,这就是所要if ( @entires == 4 )查找的内容。如果找到,仅当已打印一列行时,它才会将其打印为后续行。然后,它保存该行。if仅当该行没有三个制表符时,该行才会打印在外部。

以下较短的脚本产生相同的输出:

use strict;
use warnings;

my @file = <DATA>;

for ( my $i = 1 ; $i < $#file ; $i++ ) {

    if ( $file[$i] =~ /(?:\t\s){3}/ ) {
        print $file[ $i - 1 ];    # Preceeding line

        while ( $file[$i] =~ /(?:\t\s){3}/ and $i < $#file ) {
            print $file[ $i++ ]    # One-column line
        }

        print $file[$i];           # Succeeding line
    }
}

__DATA__
30  13387412    34.80391242 sSN_FIRST
30  13387412    34.80391242 sSN5_40
30.1             
30.2             
30.3             
30.4             
31  14740248    65.60590089 s32138223_44
31  14740248    65.60590089 s321382_LAST
Run Code Online (Sandbox Code Playgroud)

匹配/(?:\t\s){3}/三组连续的制表符和空格,只能在只有一列的行上找到。当它找到该模式时,它会打印上一行,然后进入一个while打印单列行的循环,直到找到整行或位于数组末尾。最后,打印下一行。