web-dev-qa-db-ja.com

Perl配列でアイテムを見つけるためのGrep

何かを入力するたびに、コードは常にそれが存在することを教えてくれます。しかし、入力の一部が存在しないことは知っています。なにが問題ですか?

#!/usr/bin/Perl

@array = <>;
print "Enter the Word you what to match\n";
chomp($match = <STDIN>);

if (grep($match, @array)) {
    print "found it\n";
}
16
jenglee

Grepに与える最初の引数は、一致したかどうかを示すためにtrueまたはfalseとして評価する必要があります。したがって、次のようになります。

# note that grep returns a list, so $matched needs to be in brackets to get the 
# actual value, otherwise $matched will just contain the number of matches
if (my ($matched) = grep $_ eq $match, @array) {
    print "found it: $matched\n";
}

多数の異なる値で一致する必要がある場合は、arrayデータをhashに入れることを検討する価値がある場合があります。リストを反復処理します。

# convert array to a hash with the array elements as the hash keys and the values are simply 1
my %hash = map {$_ => 1} @array;

# check if the hash contains $match
if (defined $hash{$match}) {
    print "found it\n";
}
30
stevenl

Unix grepユーティリティのようなgrep()を使用しているようですが、これは間違っています。

Perlのスカラーコンテキストの grep() は、リストの各要素の式を評価し、式が真であった回数を返します。したがって、_$match_に「true」値が含まれる場合、スカラーコンテキストのgrep($match, @array)は常に_@array_の要素数を返します。

代わりに、パターンマッチング演算子を使用してみてください。

_if (grep /$match/, @array) {
    print "found it\n";
}
_
26
Eugene Yarmash

Eugeneとstevenlが投稿したものに加えて、<>および<STDIN> 1つのスクリプトで:<>は、コマンドライン引数として指定されたすべてのファイルを反復処理(=連結)します。

ただし、ユーザーがコマンドラインでファイルを指定することを忘れた場合、STDINから読み取り、コードは入力時に永遠に待機します

2
cfi

これは List :: Utilfirst関数を使用して実行できます。

use List::Util qw/first/;

my @array = qw/foo bar baz/;
print first { $_ eq 'bar' } @array;

List::Utilのその他の関数(maxminsumなど)も役立つ場合があります

2
yko

次のような複数の配列で単一の値を確認することもできます。

if (grep /$match/, @array, @array_one, @array_two, @array_Three)
{
    print "found it\n";
}
1
Rahul

配列に文字列「hello」が含まれ、「he」を検索している場合、grepはtrueを返しますが、「he」は配列要素ではない場合があります。

おそらく、

if (grep(/^$match$/, @array))より適切。

1
venkrao