为什么Perl字符串变得不确定?

时间:2013-12-28 22:51:52

标签: string perl

将多个标量值连接成一个Perl字符串的正确方法是什么?

以下代码是故意用于调试原因的一系列语句。

my $bill_record;

$bill_record = $acct_no . " |";

$bill_record = $bill_record . defined($w_ptWtrMtrRecRef->{"mtr_addr_no"})  ?  $w_ptWtrMtrRecRef->{"mtr_addr_no"} : " "  . " |" ;

$bill_record = $bill_record . defined($w_ptWtrMtrRecRef->{"mtr_addr_str"}) ? $w_ptWtrMtrRecRef->{"mtr_addr_str"} : " " . " |" ;

$bill_record = $bill_record . defined($w_ptWtrMtrRecRef->{"mtr_addr_apt"}) ? $w_ptWtrMtrRecRef->{"mtr_addr_apt"} : " " . " |"  ;

$bill_record = $bill_record . $issue_date . " |";

|字符用作分隔符。每行将'\n终止。

在最后一行$bill_record = $bill_record . $issue_date . " |";之后 出现此错误:

Use of uninitialized value $bill_record in concatenation (.) or string at /home/ics/include/WsBillFunc.pm line 1022.
 at /home/ics/include/WsBillFunc.pm line 1022

$issue_date在分配时定义。

什么可能导致$bill_record变得未定义,将一堆标量值连接成一个字符串的正确方法是什么?

2 个答案:

答案 0 :(得分:6)

我不清楚为什么$bill_record未定义。但是如果我理解你要做的是什么,那么你就会遇到一个优先级问题:?:运算符的优先级低于连接.,所以

$bill_record = $bill_record . defined($w_ptWtrMtrRecRef->{"mtr_addr_no"})  ?  $w_ptWtrMtrRecRef->{"mtr_addr_no"} : " "  . " |" ;

被视为

$bill_record = ($bill_record . defined($w_ptWtrMtrRecRef->{"mtr_addr_no"}))  ?  $w_ptWtrMtrRecRef->{"mtr_addr_no"} : (" "  . " |") ;

我怀疑这不是你想要的。尝试添加括号:

$bill_record = $bill_record . (defined($w_ptWtrMtrRecRef->{"mtr_addr_no"})  ?  $w_ptWtrMtrRecRef->{"mtr_addr_no"} : " ")  . " |" ;

(或者使用.=作为另一位意见提供者。)

答案 1 :(得分:3)

我可能会在join

的一个声明中这样做
$bill_record = join ' |',
    map( {
        defined( $_ ) ? $_ : ' '
        } @{ $w_ptWtrMtrRecRef }{ qw( mtr_addr_no mtr_addr_str mtr_addr_apt ) }
        ),
    $issue_date,
    '';

map中我限制了parens,因为我只想将它应用于哈希切片。之后是$issue_date和空字符串。那个空字符串会得到你的最终|

但是,对于您的问题,看起来您有一个优先级问题。一种看待这种情况的方法是让Perl编译然后解压缩你的程序以查看它想要的内容。 B::Deparse模块执行此操作,并使用-p参数添加额外的括号。

这是原始程序的缩减版本,其中添加了对顶部deparser的调用(它是B::Deparse模块,但命名空间为O

#!/usr/bin/perl

use O qw(Deparse -p);

my $b;
$b = $acct_no . " |";
$b = $b . defined($w->{"no"})  ? $w->{"no"}  : " " . " |" ;
$b = $b . defined($w->{"str"}) ? $w->{"str"} : " " . " |" ;
$b = $b . defined($w->{"apt"}) ? $w->{"apt"} : " " . " |"  ;
$b = $b . $issue_date . " |";

输出:

my($b);
($b = ($acct_no . ' |'));
($b = (($b . defined($$w{'no'})) ? $$w{'no'} : '  |'));
($b = (($b . defined($$w{'str'})) ? $$w{'str'} : '  |'));
($b = (($b . defined($$w{'apt'})) ? $$w{'apt'} : '  |'));
($b = (($b . $issue_date) . ' |'));

关键部分是(($b . defined($$w{'no'}))$b的当前值与defined的返回值连接,然后条件运算符(? :)完成。如果测试值为true,则返回条件中的第一个值。

当它到达mgr_apt_no时,可能有许多记录没有设置该值。但是,之前$b$$w{'apt'}的合并值已定义,因为$b不为空。因此,它选择$$w{'apt'}的值来分配给$b。当它执行最后一行时,$b为空,以便与$issue_date进行连接。