Perl字符串eq和/或alwas是真的

时间:2015-10-13 09:22:35

标签: string perl

我正在使用XML::Parser解析xml;我的xml中有标签“my_id”和“total” 当我尝试将两者结合使用“或”时,它总是评估if为真:

if($elt eq "my_id" or "total")
{
               return 1;
               $context = $elt;
}

如果我把它分解为:

 if($name eq "my_id")
    {
          print($name." ".$xml_tag_val."\n");
          return 1;
    }
    elsif($name eq "total")
    {
           print($name." ".$xml_tag_val."\n");
          return 1;

    }

工作得很好。 第一个if有什么问题?

4 个答案:

答案 0 :(得分:4)

这里的主要问题是or不起作用。这是关于or如何运作的常见误解。您可以使用eq中的表达式,但您使用的表达式使用的or eq低于0,因此不是"total"字符串比较的一部分。此外,or-expression只会返回其中一个参数,无论哪个为真。对于字符串,除if( ( $elt eq "my_id") or "total") # ^---- -----^ 或空字符串之外的所有内容都为true。这就是您的语句始终返回true的原因:or "total"是Perl中的真实表达式。

您所写的内容可以用括号来澄清:

if( $elt eq ( "my_id" or "total") )

您可以清楚地看到or将使表达式始终为真。另请注意,执行此操作是错误的:

"my_id"

因为"total":ed表达式始终会返回if( ($elt eq "my_id") or ($elt eq "total") ) ,甚至不会检查$elt

您需要做的是对每个参数进行一次检查:

0

或者,如果您有参数列表,并且undef包含非假值(即grep或空字符串或if (grep { $elt eq $_ } @parameters) ),则可以使用{{1} }:

any

或者更准确地说,使用List::MoreUtils中的use List::MoreUtils qw(any); if ( any { $elt eq $_ } @parameters ) 功能:

DataTable mDt = new DataTable();
int startPosotion = table.InnerHtml.IndexOf("<tbody>"); // Start <tbody> from where Actual Data Exist
int endPosotion = table.InnerHtml.IndexOf("</tbody>"); // End </tbody> where Data Finish
string data = table.InnerHtml.Substring(startPosotion, (endPosotion - startPosotion) + count);
data = data.Replace("<br>", "<br></br>");

XmlTextReader xml = new XmlTextReader(new System.IO.StringReader(data));
int i = 0; // DataTable Columns
List<string> c = new List<string>();

while (xml.Read())
{
    switch (xml.NodeType)
    {
       case XmlNodeType.Text: //Display the text in each element.
            c.Add(xml.Value);
            i++;
            break;
    }

    if (i == 9)
    {
        var rows = mDt.Select("TransactionId='" + c[0] + "'");
        if (rows == null || rows.Count() == 0)
        {
            var z = c[3].ToString().Trim() + " " + c[4].ToString().Trim() + " " + c[5].ToString().Trim();
            mDt.Rows.Add(c[0].ToString().Trim(), c[1].ToString().Trim(), c[2].ToString().Trim(), z, c[6].ToString().Trim(), c[7].ToString().Trim(), c[8].ToString().Trim());
        }

        i = 0;
        c = new List<string>();
    }
}
dgvTariff.DataSource = mDt;
dgvTariff.Refresh();

答案 1 :(得分:3)

你必须写下这样的条件:

if($elt eq "my_id" or $elt eq "total")

答案 2 :(得分:0)

eq不适用于&#34;或&#34;的左侧。 eq的优先级更高,因此首先测试它。

第一个表达式实际上是:

if ( $elt eq "my id"
          or "total" );

因为&#34;总计&#34;这是一个字符串,因此是真的。你根本没有测试它的等价性。

您可以重写为:

if ( $elt eq "my id"
  or $elt eq "total" ) {
  #.... 
}

答案 3 :(得分:0)

  

$elt eq "my_id" or "total"

正如其他人所说,这不符合您的意图。使用括号,这相当于($elt eq "my_id") or "total"。表达式始终为true,因为即使$elt不是字符串 - 等于"my_id",表达式的第二部分"total"也是一个真实的表达式。


perl的座右铭是“有不止一种方法可以做到这一点。”这当然适用于此;有多种方法可以测试$elt字符串是否等于'my_id''total'

if (($elt eq 'my_id') || ($elt eq 'total')) ...
if ($elt eq 'my_id' || $elt eq 'total') ...

我更喜欢上面的第一个。我的个人运营商偏好规则:使用除$a+$b*$c等表达式之外的括号。你不需要$a+$b*$c的括号,因为每个人都知道乘法和除法在加法和减法上分布。除此之外,请使用括号。但这只是我的偏好。这样做的方法不止一种。

if ($elt =~ /^(?:my_id|total)$/) ...

这是一种完全不同的方式。括号在这里很重要。

对于另一种方法,请使用post-if:

return print("$name $xml_tag_val\n") if $elt =~ /^(?:my_id|total)$/;

你不需要那些$name." ".$xml_tag_val."\n"的东西。了解'$non_interpolated_string'"$interpolated_string"之间的区别。单引号和双引号在perl中是相当不同的野兽。