【问题标题】:Perl thinks all strings are equalPerl 认为所有字符串都是相等的
【发布时间】:2013-06-06 10:29:53
【问题描述】:

编辑:我之前确实尝试过使用 eq 而不是 ==,但它不起作用。出于某种原因,现在确实如此。可能当时还有另一个错误导致它无法工作,但现在这个问题已经解决了。谢谢。

我正在尝试做一些简单的验证。我想确保通过变量提供的重定向 url 是否以特定站点开头。如果是,则重定向通过,如果不是,则重定向到站点的根目录。看起来很简单,对吧?

$redir = $input{'redirect'};
$redir_sub = substr($redir, 0, 21);
if ($redir_sub == "http://www.mysite.com") {
     print "Location: $redir \n\n";
}else{
     print "Location: http://www.mysite.com \n\n";
}

问题是,无论我在其中放置什么变量,“if”都会返回为真。我可以把我最喜欢的网络漫画放在那里,它会重定向到它,尽管字符串不匹配。例如:

$redir = $input{'redirect'};
$redir_sub = "http://www.yahoo.com"
if ($redir_sub == "http://www.mysite.com") {
     print "Location: $redir_sub \n\n";
}else{
     print "Location: http://www.mysite.com \n\n";
}

重定向到雅虎!怎么回事?

【问题讨论】:

标签: perl if-statement substring


【解决方案1】:
if ($redir_sub == "http://www.mysite.com")

应该是

if ($redir_sub eq "http://www.mysite.com")

因为eq 是字符串相等运算符,并且使用== 强制进行数字比较,所以在这种情况下,条件总是评估为真,因为0 == 0 为真。

【讨论】:

  • 嗯。诡异的。我之前尝试过 eq ,但它没有用。现在确实如此。谢谢。
  • 就在 if 条件之前,您可以 print qq($redir_sub eq "http://www.mysite.com"); 检查正在评估的内容。
  • @MarcelMarino 不,你没有。您认为您之前尝试过。 use warnings 你会发现你的“bug”变得不那么神秘了。
【解决方案2】:

运算符== 用于比较数字。您应该将其替换为运营商eq

【讨论】:

    【解决方案3】:

    TL;DR:使用eq 而不是==


    Perl 作为一门语言似乎有一个问题:它使用相同的数据类型(标量)来处理许多不同的事物,包括字符串和数字。标量同时是两者,而不仅仅是其中之一。 Perl 没有类型注释,也没有办法指出一个变量是保存一个字符串还是一个数字。

    当我们考虑相等性测试时,这会产生问题。假设有两个标量 $a = "42.0"$b = 42。他们平等吗?是与否:

    • 字符串"42""42.0"相同的东西!这些相等。
    • 4242.0 的数字相等!

    如上所述,Perl 没有使用类型系统来解决这种歧义。相反,它使用不同的运算符集进行字符串和数字运算:

    eq ne lt le gt ge cmp
    == != <  <= >  >= <=> 
    

    【讨论】:

    • also ~~ 智能匹配运算符可用于字符串和数字比较。 42 ~~ "42";42 ~~ "42.0";42 ~~ "42\n";42 ~~ "42 " 将是真的
    • @Suic 为此使用智能匹配是一个相当糟糕的主意,因为"42" ~~ "42.0" 不会评估为真。对于这种比较,最好明确地使用字符串或数字比较。另一种选择是明确地对智能匹配参数进行数字化/字符串化:0+$a ~~ 0+$b"$a" ~~ "$b"。此外,智能匹配行为可能会在即将发布的 perl 版本中发生变化。
    【解决方案4】:

    你的问题是你没有使用

    use warnings;
    

    这就是 Perl 允许你犯这个错误的原因。您正在使用数字相等运算符来比较字符串。因此,Perl 首先尝试将每个参数转换为数字。而且由于您的字符串不是以数字开头(并且看起来不像数字),因此它们将被转换为零0。所以你的表情

    if ($redir_sub == "http://www.mysite.com")
    

    真的是这个意思

    if (0 == 0)
    

    当然总是返回 true。

    如果你一直使用警告,你会得到错误:

    Argument "http..." isn't numeric in numeric eq (==) at ...
    Argument "http..." isn't numeric in numeric eq (==) at ...
    

    这暗示了您应该使用eq 而不是== 来比较字符串。

    【讨论】:

      【解决方案5】:

      == 进行数值比较。 eq 进行字符串比较。当您使用字符串作为数字时,perl 将您的字符串传递给您的 c 库的 aton()。所以你实际上是在询问你的计算机 0 == 0 是否为真。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-27
        相关资源
        最近更新 更多