PERL:使用破折号阅读社会保障#的正则表达式

时间:2017-02-13 16:56:05

标签: sql regex perl informix isql

我正在编写一个perl脚本,它从文件中读取社会安全号码,在多个表中查找信息并输出到分隔文件。我用PERL 5写作并与IBM informix打交道。我觉得这是我的REGEX问题。我得到以下错误的多行:

DBD :: Informix :: st执行失败:SQL:-1213:数字转换过程中的字符在./corylist.pl第61行第461行失败。 DBD :: Informix :: st fetchrow_array失败:SQL:-400:尝试取消打开游标。在./corylist.pl第63行,第461行。

有人可以向我推正正确的方向吗?谢谢!

while(<IN>) {
    $id = $_;
    chomp $id;
    $id =~ m/^\d{3}-\d{2}-\d{4}$/;
    #print "$id\n";

$STMT = <<EOF;
select  i.ss_no,
    i.fullname,             i.firstname,i.lastname,i.addr_line1,i.addr_line2,i.city,i.st,i.zip,r.res_ctry,r.res_cty,
    i.phone,NVL(aa.phone," ") cell,NVL(a.line1," ") stuemail,NVL(pa.line1," ") peremail

  from  id i,
    prof r,
    outer aa_rec a,
    outer aa_rec aa,
    outer aa_rec pa
where   i.ss_no = $id
and     i.id = r.id
and     i.decsd <> "Y"
and a.id = i.id and a.aa = "EML" and a.end_date is null
and pa.id = i.id and pa.aa = "OEML" and pa.end_date is null
and pa.beg_date = (select max(beg_date) from aa_rec where aa = "OEML" and id=$id and end_date is null)
and aa.id = i.id and aa.aa = "CELL" and aa.end_date is null
group by     ss_no,fullname,firstname,lastname,addr_line1,addr_line2,city,st,zip,res_ctry,res_cty,phone,cell,stuemail,peremail
order   by fullname, ss_no
EOF

$sth = $db1->prepare($STMT);
$sth->execute();

while (($id,$fullname,$fname,$lname,$addr1,$addr2,$city,$st,$zip,$ctry,$cnty,$phone,$cell,$stuemail,$peremail) = $sth->fetchrow_array()) {

    $x = $id." | ". $fullname." | ";
    $x .= $fname." | ".$lname." | ".$addr1." | ".$addr2." | ".$city." | ".$st." | ".$zip." | ".$ctry." | ".$cnty." | ";
    $x .= $phone." | ".$cell." | ".$stuemail." | ".$peremail." | \n";
    print $out_fh $x;
}

1 个答案:

答案 0 :(得分:4)

你的正则表达式很好,但它没有做任何事情。

$id =~ m/^\d{3}-\d{2}-\d{4}$/;

如果$id与模式匹配,则该行将为true。它没有别的。

  

字符到数字转换过程失败

错误消息显示您的数据库想要一个数字,但得到的东西无法转换它得到的东西。由于您在查询中使用$id,因此必须使用短划线。因此,假设您的SSN是某种整数,那就省了。

摆脱错误消息的最简单方法是删除任何不是数字的内容。这将消除破折号-以及其他人们想要输入的内容。

while ( my $id = <IN>) {
    chomp $id;
    $id =~ s/\D//g; # remove any non-digits

    # ...
}

现在你可以进行插入了。但是,如果没有适当的引用,您应该直接将变量直接写入SQL中来插入数据。那是an invitation for SQL injection。相反,请使用placeholders

my $sql = "SELECT * FROM foo WHERE bar=?";

现在当您execute语句prepare时,您传递了$id

my $sth = $dbh->prepare($sql);
$sth->execute($id);

如果您正在处理大型文件,最好使用fetchrow_arrayreffetchrow_hashref代替fetchrow_array,因为所有变量的复制都是如此很贵。另请查看this presentation以了解有关快速使用DBI的更多信息。

您可能希望查看SSN::Validate以实际验证社会安全号码。如果您使用它,似乎您不需要进行上面建议的清理。

您还可以查看Text::CSV以获得创建CSV输出的更简洁方法。