perl一次读取多行文本的策略

在处理文本时,常常遇到这样的情况:就是我们需要把两行文本做一个比较,然后选择性输出。而在while(<FILEHAND>){do something}程序块中默认只能一次读取一行。笔者在这里,举一个简单的例子来说明怎么处理这种情况。

有一个这样一段文本:

a 1 2 3 4
a 5 6 7 8
a 6 7 8 9
a 7 8 9 11
a 7 8 9 12
a 13 12 14 15
a 18 14 16 17
a 2 3 4 65


要求是这样的:如果上一行的第5列数字大于下一行第二列的数字,就把这两行都输出。

策略一:把输入文本存放到数组中,然后利用for循环,一次输出两行做判断。

脚本如下:

#! /usr/bin/perl -w
use strict;
chomp(my @a=<DATA>);
my @out;
for(my $i=0;$i<$#a;$i++){
        my ($a1,$a2)=(split/\s+/,$a[$i])[1,4];
        my ($b1,$b2)=(split/\s+/,$a[$i+1])[1,4];
        push @out,@a[$i,$i+1]  if $a2 > $b1;
}
my %ha;
my @new=grep {$ha{$_}++<1}@out;
print $_,"\n" for@new;
__DATA__
a 1 2 3 4
a 5 6 7 8
a 6 7 8 9
a 7 8 9 11
a 7 8 9 12
a 13 12 14 15
a 18 14 16 17
a 2 3 4 65

策略一思路比较简单,但是如果输入文本过大,比较消耗内存。当然使用Tie::File模块又是另外一回事情了。

在这里,笔者利用tell和seek函数,对句柄定位做一下调整,就可以在while循环中,实现一次输出多行,一行多次输出了,是不是很方便呢?

代码如下:

#! /usr/bin/perl -w
use strict;
my @out;
while(<DATA>){
        chomp;
        my $pos=tell(DATA);
        my @a=split/\s+/,$_;
        my $sec=<DATA>;
        if($sec){
                chomp$sec;
                my @b=split/\s+/,$sec;
                if($a[4]>$b[1]){
                        push @out,$_,$sec;
                }
        }
        seek(DATA,$pos,0);
}
my %ha;
my @new=grep $ha{$_}++ < 1,@out;
print $_,"\n" for@new;
__DATA__
a 1 2 3 4
a 5 6 7 8
a 6 7 8 9
a 7 8 9 11
a 7 8 9 12
a 13 12 14 15
a 18 14 16 17
a 2 3 4 65


程序运行的结果如下:

a 5 6 7 8
a 6 7 8 9
a 7 8 9 11
a 7 8 9 12
a 18 14 16 17
a 2 3 4 65


__结束__

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值