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

PERL: Regular Expression for reading Social Security # with Dashes

我正在编写一个 perl 脚本,它从一个文件中读取社会安全号码,跨多个表查找信息并输出到一个带分隔符的文件。我正在使用 PERL 5 编写并处理 IBM informix。我觉得问题出在我的正则表达式上。我收到多行以下错误:

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

你的正则表达式没问题,但它什么也没做。

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

如果 $id 与模式匹配,则该行为真。它什么都不做。

A character to numeric conversion process failed

错误信息说你的数据库想要一个数字,但是得到了一些它不能转换它得到的东西。由于您在查询中使用了 $id,所以那一定是破折号。因此,假设您的 SSN 是某种整数是省事的。

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

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

    # ...
}

现在可以插入了。但是你真的不应该在没有正确引用的情况下通过将变量直接写入你的 SQL 来插入数据。那是 an invitation for SQL injection. Instead, use placeholders.

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

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

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

如果您正在处理 文件,使用 fetchrow_arrayreffetchrow_hashref 代替 fetchrow_array 可能是个好主意,因为所有变量的复制都非常昂贵。另请参阅 this presentation 以了解有关快速使用 DBI 的更多信息。

您可能想查看 SSN::Validate 以实际验证社会安全号码。如果你使用它,似乎你不需要执行上面建议的 clean-up。

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