Grep, чтобы найти элемент в массиве Perl - PullRequest
16 голосов
/ 26 октября 2011

Каждый раз, когда я что-то вводю, код всегда говорит мне, что он существует. Но я знаю, что некоторые входные данные не существуют. Что не так?

#!/usr/bin/perl

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

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

Ответы [ 6 ]

30 голосов
/ 26 октября 2011

Первый аргумент, который вы передаете 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";
}
26 голосов
/ 26 октября 2011

Вы, похоже, используете grep() как утилиту Unix grep, что неправильно.

Perl's grep() в скалярном контексте оценивает выражение для каждого элемента списка и возвращает число раз, когда выражение было истинным. Поэтому, когда $match содержит какое-либо "истинное" значение, grep($match, @array) в скалярном контексте всегда будет возвращать количество элементов в @array.

Вместо этого попробуйте использовать оператор сопоставления с образцом:

if (grep /$match/, @array) {
    print "found it\n";
}
2 голосов
/ 26 октября 2011

Это можно сделать с помощью функции List :: Util * first:

use List::Util qw/first/;

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

Другие функции из List::Util, такие как max, min, sum также могут быть полезны для вас

2 голосов
/ 26 октября 2011

В дополнение к тому, что опубликовали Евгений и Стивенл, вы можете столкнуться с проблемами при использовании <> и <STDIN> в одном скрипте: <> выполняет итерацию (= объединение) всех файлов, заданных в качестве аргументов командной строки.

Однако, если пользователь когда-либо забудет указать файл в командной строке, он будет читать из STDIN, а ваш код будет ждать вечно при вводе

1 голос
/ 07 апреля 2015

Вы также можете проверить одно значение в нескольких массивах, например,

if (grep /$match/, @array, @array_one, @array_two, @array_Three)
{
    print "found it\n";
}
1 голос
/ 01 июня 2013

Может случиться так, что если ваш массив содержит строку "hello", и если вы ищете "he", grep возвращает true, хотя "he" может не быть элементом массива.

Может быть,

if (grep(/^$match$/, @array)) больше возможностей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...