perl文件句柄的理解(tell、seek)以及文本多行匹配的一种算法

下述理解,完全是个人体会。自觉有点道理。

perl文件句柄的理解

句柄,又叫指针;下文,我也称之为头地址,因为更形象一些。
文件句柄,就是指向文件内容的内存空间范围的头地址;文件句柄读取一次,起始地址+1,即读取下一行(perl里默认是一行一行读取文本的。可以设置间隔符$/,使之不是\n)。这一段,是个人体会,不知正确否。以硬件角度,类似FIFO及FIFO读指针(ps:先入先出,而非堆栈,FILO,先入后出)

qilei@AFAAW-704030720:~$ cat test.txt
a11111
a22222
a33333
a44444
a55555
a66666
a77777
a88888
a99999
a00000
b11111
b22222
b33333
b44444
b55555
b66666
b77777
b88888
b99999
b00000
qilei@AFAAW-704030720:~$ cat simple.pl
#!/usr/bin/perl
use strict;
use warnings;

my $fileh_pos;
open my $fileh,"<", $ARGV[0] or die "error:file can't open";
my $line1=<$fileh>;
print $line1;
my $line2=<$fileh>;
print $line2;

qilei@AFAAW-704030720:~$ ./simple.pl  test.txt
a11111
a22222
qilei@AFAAW-704030720:~$

如下面举例,连续两次读取文件句柄$fileh,发现第二次读取文件句柄【特指while(<$fileh>)】,地址已经递增操作了,而不是从第一行读取test.txt的内容。


qilei@AFAAW-704030720:~$ cat b.pl
#!/usr/bin/perl
use strict;
use warnings;

open my $fileh,"<", $ARGV[0] or die "error:file can't open";
while(<$fileh>){
        if($_ =~ /a33333/) {
                print $_;
                while(<$fileh>){
                        print $_;
                }
        }
}
qilei@AFAAW-704030720:~$ ./b.pl test.txt
a33333
a44444
a55555
a66666
a77777
a88888
a99999
a00000
b11111
b22222
b33333
b44444
b55555
b66666
b77777
b88888
b99999
b00000

文本多行匹配的一种算法

网上介绍的一种算法,是基于tell和seek。这个在后面会介绍。

这里的算法,可以看做是基于嵌套循环。ps:根据实际需求,可以灵活使用last和next。
如果在第二次while(<$fileh>)的时候增加判断条件,就可以依据第一次匹配关键词“a33333”这个前提条件,做第二次匹配。

qilei@AFAAW-704030720:~$ cat b.pl
#!/usr/bin/perl
use strict;
use warnings;

open my $fileh,"<", $ARGV[0] or die "error:file can't open";
while(<$fileh>){
        if($_ =~ /a33333/) {
                print $_;
                while(<$fileh>){
                        if($_ =~ /7777/) {
                                print $_;
                                last;
                        }
                }
        }
}
qilei@AFAAW-704030720:~$ ./b.pl test.txt
a33333
a77777
qilei@AFAAW-704030720:~$

seek - reposition file pointer for random-access I/O

定位指针,即记录文件句柄的地址。
可以记录文件句柄的头地址、中间地址、末地址。

seek - perldoc.perl.org
http://perldoc.perl.org/functions/seek.html

tell - get current seekpointer on a filehandle

获取之前定位的指针。

tell - perldoc.perl.org
http://perldoc.perl.org/functions/tell.html

seek和tell一般是配套使用。

下面的例子,包含了seek和tell的用法。而且从另一角度,解释了文件句柄头地址的理解。

例子:连续执行两次while(<$fileh>)的结果

可以看出,第二次执行while(<$fileh>)的时候,文件句柄已经读不出任何内容了。

qilei@AFAAW-704030720:~$ cat test.txt
a11111
a22222
a33333
a44444
a55555
a66666
a77777
a88888
a99999
a00000
b11111
b22222
b33333
b44444
b55555
b66666
b77777
b88888
b99999
b00000
qilei@AFAAW-704030720:~$ cat a1.pl
#!/usr/bin/perl
use strict;
use warnings;

open my $fileh,"<", $ARGV[0] or die "error:file can't open";
while(<$fileh>){
        if($_ =~ /3333/) {
                print $_;
        }
}

while(<$fileh>){
        if($_ =~ /7777/) {
                print $_;
                last;
        }
}
qilei@AFAAW-704030720:~$ ./a1.pl test.txt
a33333
b33333
qilei@AFAAW-704030720:~$

增加tell和seek的使用

tell的作用,是记录文件句柄的头地址,即位置。
seek有三个参数,
1. 文件句柄;
2. 依据第三个参数,提供相对于头地址的相对位置;
3. 如下:
0代表文件开头的位置。即重新开始,类似先close $fileh,然后再open $fileh的效果。
1代表当前头地址的位置;
2代表文件末尾的位置。

qilei@AFAAW-704030720:~$ cat a2.pl
#!/usr/bin/perl
use strict;
use warnings;

my $fileh_pos;
open my $fileh,"<", $ARGV[0] or die "error:file can't open";
while(<$fileh>){
        if($_ =~ /3333/) {
                $fileh_pos=tell $fileh;
                print $_;
        }
}

seek($fileh,$fileh_pos,0);
while(<$fileh>){
        if($_ =~ /7777/) {
                print $_;
                last;
        }
}
qilei@AFAAW-704030720:~$ diff a1.pl a2.pl
4a5
> my $fileh_pos;
7a9
>               $fileh_pos=tell $fileh;
11a14
> seek($fileh,$fileh_pos,0);
qilei@AFAAW-704030720:~$ ./a2.pl test.txt
a33333
b33333
b77777
qilei@AFAAW-704030720:~$

参考文档

Perl特殊变量
http://www.yiibai.com/perl/perl_special_variables.html
Perl参考函数
http://www.yiibai.com/perl/perl_function_references.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值