将多个标量值连接成一个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
变得未定义,将一堆标量值连接成一个字符串的正确方法是什么?
答案 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
进行连接。