String 为什么Perl字符串变得不定义?
将几个标量值连接成一个Perl字符串的正确方法是什么 出于调试原因,下面的代码是一系列语句String 为什么Perl字符串变得不定义?,string,perl,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 = $b
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\u record=$bill\u record之后$发行日期。" |";代码>
出现以下错误:
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\u date
在分配时定义
是什么原因导致$bill\u record
未定义,以及将一组标量值连接成一个字符串的正确方法是什么?我不知道为什么$bill\u 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"} : " ") . " |" ;
(或者按照另一位评论员的建议使用=
)我可能会在一句话中用一个:
在这种情况下,我使用parens进行限制,因为我只想将其应用于哈希切片。之后是$issue\u date
和空字符串。该空字符串获取您拥有的最后一个
但是,对于你的问题,看起来你有一个优先权问题。了解这一点的一种方法是让Perl编译程序,然后对程序进行分解,以查看它认为您需要什么。模块执行此操作,我使用-p
参数添加额外的括号
这里是原始程序的精简版本,在顶部添加了对deparser的调用(它是模块,但名称空间是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
的当前值与的返回值串联,然后执行条件运算符(?:
)。如果测试值为真,则返回条件中的第一个值
当它到达mgr\u apt\u no
时,可能有许多记录没有设置该值。但是,前面的$b
和$$w{'apt'}
的组合值是定义的,因为$b
不是空的。因此,它选择$$w{'apt'}
分配给$b
。当它执行最后一行时,$b
为空,以便与$issue\u date
串联,首先使用$bill\u record.=…
而不是$bill\u record=$bill\u record.
将使其更易于阅读。此外,我将添加足够的参数,以便调整操作顺序这是显而易见的。@woolstar很好,但为什么呢?我认为使用原始标量$bill_记录并使用
也会起作用。构建数组然后连接(“|,…)可能会更干净
it,IMO,这比一堆字符串串联更符合您的意图。您可能应该查找运算符(及其相对值,/
),以及=
。它们允许您编写:$bill\u record.=($w\u ptWtrMtrRecRef->{“mtr\u addr\u no”}/')。“\124;”;
,这是一个比在页面右侧滚动的表达式更容易阅读的堆。这确实假设您至少有Perl 5.10,IIRC;但是您现在应该使用5.18了(或者如果您有一个反向的O/S,比如Mac OS X 10.9.1 Mavericks,它提供5.16.2)。您所说的不是真的。这可能不是您的代码,或者在发出该消息时,$issue\u 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) . ' |'));