Perl的。使用功能之前, [英] Perl. Using until function

查看:153
本文介绍了Perl的。使用功能之前,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的数据文件。文件中每行有四个元素。有些线路都充满了无空白项。其他线路都装了空间中的第一项,其余三人都是空白的,或者说。这是一个制表符分隔的文件。

输入文件的示例:

 
    。
    。
    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
    。
    。
    。

要重申的空白在我的文件实际上包含一个空间,如果这个问题。

我的总体目标是(第四列被忽略)以填充的第二和第三列在整个文件。为了做到这一点,我需要我的脚本来识别套连续行是空白,加上该行立即preceding和紧接着的一组连续的空行的行。在上面的例子中,这将是线2 - 7。一旦我能做到这一点,我可以使用在侧翼线,都充满了信息,帮助填写中的台词缺少的条目之间

我一直与试验,直到的功能,但我不会在一个循环,读取行数据线连接它做成功。例如,我可以读线和找到空行:

 打开(我的$ FILE,< $映射文件);
我@file =< $文件&gt ;;
关闭$文件;为(我的$ I = 1; $ I<标@file; $ I ++)
    {
     我@entries =拆分('\\ T',$文件[$ i]);
     如果($条目[1] =〜米/ /)
        {
         打印$文件[$ i]\\ n。
        }
    }

不过,我想聘请直到的功能,以便读线和搜索的连续组线我要找(空白行加2侧翼全线)。例如:

 ,直到($文件[线路] =〜M / /&放大器;&安培; $文件[另一行] =〜M / /)
    {
     我在这里线性插值;
    }

谁能给我一个关于如何对夫妇的方式来读取阵列和比较线发现我整个文件需要套暗示?


解决方案

或许下面会有所帮助:

 使用严格的;
使用警告;我($最后,$ oneColumn);我@file =<数据取代;我的$线(@file){
    我@entires =分裂',$线;    如果(@entires == 4){
        如果($ oneColumn){
            打印$行; #后继行
            $ oneColumn = 0;
        }
        最后$ = $行;
        下一个;
    }    打印$持续在$最后; #preceeding线
    民主基金最后$;
    打印$行; #一列线
    $ oneColumn = 1;}__数据__
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

输出:

  30 13387412 34.80391242 sSN5_40
30.1
30.2
30.3
30.4
31 14740248 65.60590089 s32138223_44

一个'全',行应该有 @entries 四大要素,这就是如果(@entires == 4)查找。如果找到,它会打印为仅适用于已印制一列线后继行。然后,这样可以节省线路。线条打印外如果只有当行不有三个标签。

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

 使用严格的;
使用警告;我@file =<数据取代;为(我的$ I = 1; $ I< $#文件; $ I ++){    如果($文件[$ i] =〜/(?:\\ t \\ S){3} /){
        打印$文件[$ I - 1]; #preceeding线        而($文件[$ i] =〜/(?:\\ t \\ S){3} / $和I< $#文件){
            打印$文件[$ I ++]#一列线
        }        打印$文件[$ i]; #后继行
    }
}__数据__
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

/(?:\\ t \\ S){3} / 匹配连续三套标签和空间,这只会在一行中找到只有一个柱。当它发现模式,它打印previous线,然后进入,而循环,直到全线是在发现或打印一列线数组的末尾。最后,后继行打印

I have a simple data file. Each line in the file has four elements. Some lines are filled with no blank entries. Other lines have a first entry and the remaining three are blank, or rather "filled" with a space. It is a tab delimited file.

Example of the input file:

    .
    .
    .
    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
    .
    .
    .

To reiterate, the "blanks" in my file actually contain a single space, if this matters.

My overall goal is to "fill in" the second and third column (the fourth column is ignored) throughout the file. In order to do that, I need my script to identify sets of consecutive lines that are blank, plus the line immediately preceding and the line immediately succeeding the set of consecutive blank lines. In the example above, this would be lines 2 - 7. Once I can do that, I can use the information in the flanking lines, which are filled, to help "fill in" the missing entries in the lines in between.

I have been experimenting with the until function, but I'm not succeeding in coupling it with a loop that reads the data line for line. For example, I can read the lines and find the blank lines:

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";
        }
    }

But I am trying to employ the until function, so as to read lines and search for the consecutive set of lines I am looking for ("blank" lines plus the two flanking "full" lines). For example:

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

Can anyone give me a hint about how to couple a way to read the array and compare lines to find the sets I need across the file?

解决方案

Perhaps the following will be helpful:

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

Output:

30  13387412    34.80391242 sSN5_40
30.1
30.2
30.3
30.4
31  14740248    65.60590089 s32138223_44

A 'full', line should have four elements in @entries, and that's what if ( @entires == 4 ) looks for. If found, it'll print it as the succeeding line only if one-column lines have been printed. Then, it saves the line. Lines are printed outside the if only when the line doesn't have three tabs.

The following, shorter script produces the same output:

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

The /(?:\t\s){3}/ matches three consecutive sets of tab and space, which would only be found on a line with just one column. When it finds that pattern, it prints the previous line, then enters a while loop that print the one-column lines until a full line is found or it at the end of the array. Finally, the succeeding line is printed.

这篇关于Perl的。使用功能之前,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆