3

perlにサブルーチンがあり、配列に特定の要素が含まれているかどうかをチェックし、TRUEを返します。それ以外の場合はfalseを返します。検索された要素http_TestABCは配列に含まれていないため、次のコードはfalseに戻りますが、それでも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、2番目の引数をに割り当てます$entity。したがって、もちろん、1つの要素をすべてチェックする$entityと、それらの1つになります。

また、サブ名の後に続く括弧であるプロトタイプは使用しないでください。それらが何をするかを知らない限り、それらは非常に特別な機能を持っているので、無視するのが最善です。

解決策は、引数を逆にします。

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 (\@$) {

次に、とのように、実際に配列を引数として渡すことができpushます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 に答える