3

我在 perl 中有一个子例程来检查数组是否包含特定元素,如果它包含返回 TRUE,否则返回 false。下面的代码应该返回 false,因为搜索到的元素 http_TestABC 不在数组中但它仍然返回 TRUE。无法弄清楚为什么会发生这种情况.任何指针表示感谢

#!/usr/bin/perl

use strict;
use warnings;


my @result_listosp;     # defines an empty array

$result_listosp[0] = "origin-server-pool-1"; # array has one element
$result_listosp[1] = "http-pool-OSP2"; # array has 10 elements now
my $osp="http_TestABC";
my $status_osp_check= check_if_entity_exists(@result_listosp,$osp);
print $status_osp_check;

sub check_if_entity_exists()
{
    my @entityarray = @_;
    my $entity = $_[1];

    my $status="FALSE";

    if ( grep( /^$entity$/, @entityarray ) ) {
      $status="TRUE";
      return $status;
    }
    else {
      return $status;
    }
}
4

1 回答 1

12

它总是返回 true,因为您误解了如何将参数传递给子例程。当你这样做时:

my @entityarray = @_;
my $entity = $_[1];

您将所有参数分配给@entityarray,并将第二个参数分配给$entity。因此,当然,如果您检查一个的所有元素,$entity它将是其中之一。

您也不应该使用原型,即子名称后面的括号。除非您知道它们的作用,否则最好忽略它们,因为它们具有非常特殊的功能。

解决方案,颠倒参数:

check_if_entity_exists($foo, @bar);
...
sub check_if_entity_exists {
    my $entity = shift;     # the first arg
    my @entityarray = @_;   # the rest

发生这种情况是因为 perl 在将数组作为参数传递时将其展平,因此它只是参数列表中的元素,而不是单个变量。Perl 无法知道您是否传递了一个数组。除非你玩原型。除了作为练习之外,我不建议这样做。如果您执行以下操作:

sub foo (\@$) {

然后,您实际上可以将数组作为参数传递,就像pushand一样shift

您还可以将数组作为参考传递,在这种情况下,您可以执行以下操作:

foo(\@array, $var);

sub foo {
    my $aref = shift;    # @$aref is now @array
    my $var  = shift;

在这种情况下,您需要注意您使用的数组与传递给子例程的数组相同,而不是副本。因此,如果您更改它,则更改是永久性的。

注意:正如PSIAlt指出的那样,如果您的意图是按字面匹配,则不应直接在正则表达式中使用任意字符串。其中可能有导致副作用的元字符。执行以下任一操作:

grep /^\Q$entity/, ..       # quote meta characters
grep { $_ eq $entity } ...  # check string equality

正如 PSIAlt 建议的那样,eq是最直接的解决方案,除非您需要正则表达式功能,否则可能应该是您使用的解决方案。

于 2013-03-27T14:23:53.890 回答