perl系列:出错的perl程序

该博文将陆续列出本人编程过程中出现一些错误,供大家参考。

1、输出相反字符串
$a="abcde";
print reverse($a),"\n";    #输出“abcde”
原因:print要求列表,因此reverse把$a当作包含一个元素的列表,即($a),然后把该列表所有元素以相反顺序返回。但由于该列表只有一个元素,因此返回结果和原列表相同。
修正:使其处于标量上下文环境。方法至少有两个。
print scalar reverse($a),"\n";    #使用scalar强行规定标量上下文
print reverse($a)."\n";    #使用字符串连接符将其置于标量上下文

2、逻辑操作符的短路操作
opendir D1,"test" || die "no exist";    #当test不存在时,并没有输出出错信息
原因:"||"的优先级比较高,原句相当于opendir D1,("test" || die "no exist");
修正:使用括号或使用or
opendir (D1,"test") || die "no exist";
opendir D1,"test" or die "no exist";    #个人认为这个更好

3、比较操作符的正确使用
if (a == b) {print "true\n";} else {print "false\n";}    #输出true
原因:'=='用于数字比较,字符比较应使用'eq'
修正:
if (a eq b) {print "true\n";} else {print "false\n";}    #输出false
    #这个错误原因很简单,但犯了不止一次错误
    #在这里经常犯的另一个错误是把'=='写成'='

4、while循环对$_的影响1
my @a=1..5;
for (@a) {
    open FILEIN,'< ../temp';
    while (<FILEIN>) {/A/;}
    $_++;
    }
print "@a\n";    #输出"1 1 1 1 1"
原因:可能是while循环后没有将$_恢复原值
    将while换成for,则输出"2 3 4 5 6"
    不知道算不算bug
修正:根据具体情况有多种修正方式
    但最保险的是不要在while循环之后使用$_

5、while循环对$_的影响2
my @a=0..9;
print @a,"\n";    #输出"0123456789"
&Read(@a);
print "@a-end\n";    #输出"         -end"
sub Read {
    for (@_) {
        open FILE,'< temp';
        /A/ while <FILE>;
        }
    }
原因:仍然是while循环后$_没有恢复原值,而while最后读取的是结束标志
    同时$_和@_又可以直接修改调用参数
修正:除非要修改调用参数
    否则最好在子程序开始的时候将@_的内容赋予其他变量
另:在使用use warnings时,会有警告信息。

6、print的一个“异常”
环境:ubuntu12.04.1,perl 5.14.2,GNOME终端3.4.1.1
for (0..9) {
    print $_;
    sleep 1;    #暂停1s
    }
    #10s内看不到任何输出,10s后一次性输出0123456789
原因:命令行窗口一次输出一行,而在循环结束以前这一行没有结束
    因此直到循环结束,才一次性输出
修正:这个应该不是perl的问题
    若想每个循环都有输出,加一个换行符即可。

7、windows下文本文件多余的回车符
windows下文本文件的行尾是“\r\n",而chomp只能去掉最后的"\n"。
可使用"s/\r//"将所有的"\r"删掉。

8、shift的误用
@a=1..10;
$a=shift @a if shift @a;
print "$a\n";    #输出2
原因:本意是如果能从@a中去除元素,则输出该元素。
    但实际上是对@a进行了两次shift操作。
修正:$a=shift @a if @a;
    该错误同样适用于pop、push、unshift。

9、文件句柄没有关闭导致的错误
程序:
    open Fout,'> temp';
    print Fout 1..10;
    open Fin,'< temp';
    my $a = <Fin>;
    $a? print "yes\n" : print "null\n";    #输出null
原因:Fout没有关闭,所以print的输出还没有及时写入文件,导致Fin调用时找不到内容
修正:
方法1:及时关闭Fout。
    open Fout,'> temp';
    print Fout 1..10;
    close Fout;
    open Fin,'< temp';
    my $a = <Fin>;
    $a? print "yes\n" : print "null\n";    #输出yes
方法2:两个句柄同名
    open Fout,'> temp';
    print Fout 'a' x 10;
    open Fout,'< temp';
    my $a = <Fout>;
    $a? print "yes\n" : print "null\n";    #输出yes
注意:前面程序中,由于往程序中写入内容较少,所以全部内容都没有写入。但当写入内容非常多时,会写入部分内容,导致容易判断错误
    open Fout,'> temp';
    print Fout 'a' x 100000;
    open Fin,'< temp';
    my $a = <Fin>;
    $a? print "yes\n" : print "null\n";    #输出yes
    print length($a),"\n"    #输入98304

10、正则表达式非贪心匹配的误用
程序:
    my $_="123-456-789";
    my $b=$1 if /-(.+?)$/;    #想匹配789
    print "$b\n";    #输出456-789
原因:正则表达式从左往右匹配,先找到第一个'-',然后逐个字符匹配直到字符串结尾
修正:my $b=$1 if /.+-(.+?)$/;

11、三目操作符(条件操作符)的误用 程序:     my $a=1;     $a? $a += 2 : $a -= 3;     print "$a\n";    输出0 原因:三目操作符的结果可以赋值,如$a>$b? $a : $b = 0;(将较大的数赋值为0)     因此原程序中的 ‘$a? $a += 2 : $a -= 3;’ 相当于 ‘($a? $a += 2 : $a) -= 3;’ 修正:$a? ($a += 2) : ($a -= 3);

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...