perl的grep用法
grep operator接受一个列表和一个“测试表达式”作为参数。
它从list中一个个的取出元素,然后放到$_变量中。接着在标量环境中,对测试表达式进行估值。如果表达式的结果是true,grep就把$_放到结果list中。
在一个列表环境中,grep operator返回一个列表。在标量环境中,返回列表元素的个数。
my @results = grep EXPR, @input_list;
my $count = grep EXPR, @input_list;
这里,EXPR代表任何显式或隐式地引用$_的标量表达式。
例如,要找出list中所有大于10的数(显式的引用$_):
my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
my @bigger_than_10 = grep $_ > 10, @input_numbers;
隐式的调用$_(找出所有以4结尾的数字):
my @end_in_4 = grep /4$/, @input_numbers;
$_不是列表元素的copy,而是他们的别名,就像foreach中一样。
如果测试表达式逻辑比较复杂,可以封装为函数:
my @odd_digit_sum = grep digit_sum_is_odd($_), @input_numbers;
sub digit_sum_is_odd {
my $input = shift;
my @digits = split //, $input; # Assume no nondigit characters
my $sum;
$sum += $_ for @digits;
return $sum % 2;}
除了上面的表达式形式,还有另一种块形式。不是显式的定义一个函数,我们可以只把函数的主体部分放在grep中。
注意:块后面没有逗号。
my @odd_digit_sum = grep {
my $input = $_;
my @digits = split //, $input; # Assume no nondigit characters
my $sum;
$sum += $_ for @digits;
$sum % 2;
} @input_numbers;
注意这个块和上面函数形式的区别。
再从http://blog.chinaunix.net/u/10363/showart.php?id=51326参照一些例子。
♣剔除list中重复的元素:
my @arr_str = qw(a ba c a a e f c e);
my @unique_str = grep {++$count_hash{$_} < 2} @arr_str;
print Dumper(@unique_str);
♣找出list中出现两次的元素:
应用两次grep
my @arr_twice = grep {$count_hash{$_} == 2} grep {++$count_hash{$_} > 1} @arr_str;
♣找出当前目录的文本文件:
my @files = grep { -f and -T } glob '* .*';
glob返回的是一个文件列表, -f and -T匹配列表的元素(先判断-f效率高一些)。
♣选择数组元素并消除重复:
my @array = qw(To be or not to be that is the question);
my @found_words =
grep { $_ =~ /b|o/i and ++$counts{$_} < 2; } @array;