使用Regex / Grep使用模式数组从数组中获取行

时间:2011-07-26 14:30:44

标签: regex perl grep

在网上到处搜索,并成为perl的菜鸟,为了解决这个问题,我决定在Stack上发帖。

我希望做的是循环遍历包含所需匹配的array1(它们每次都会不同,并且可能包含许多模式(需要匹配的井字符串)但是使用这个例子以便我能理解这个问题)。然后针对使用包含一些字符串的array2的grep测试每个元素。然后打印出grep找到的与所用模式匹配的行。

#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw( strftime );
my (@regressions,@current_test_summary_file,@regression_links);

@regressions = ("test","table");
@current_test_summary_file = ("this is the line for test \n","this is the line for    table \n","this is the line for to\n");
foreach (@regressions)
{
print $_ . "\n";    
@regression_links = grep(/$_/, @current_test_summary_file);
}

foreach(@regression_links)
{
print $_ . "\n";
}

所以我想只选择前两个元素,而不是现在正在发生的所有三个元素。

希望我已经正确地解释了我的问题。我已经尝试了很多东西(例如使用qq)但是只使用grep来尝试这个(不确定我如何使用不同的方法来实现这种方法)。如果有人可以指出我正确的方向(以及我是否应该使用grep来解决这个问题)我将非常感激。刚试过下面这段代码,而不仅仅是得到任何想法的第二个元素? (抱歉无法回复你的评论某些原因,但所以你知道axeman的第二个想法是有效的。)

foreach my $regression (@regressions)
{
print $regression . "\n";   
@regression_links = grep(/$regression/, @current_test_summary_file);
}

2 个答案:

答案 0 :(得分:4)

grep内,$_指的是测试中涉及的列表元素。 /abc/也是$_ =~ /abc/的缩写,因此您有效地测试$_ =~ /$_/猜测答案可能是什么(没有元字符)?

因此,您将所有值都传递到@regression_links

您需要做的是保存 $_的值。但是,由于您没有使用简单的print语句,您可以轻松地为grep保留$_变量,如下所示:

foreach my $reg ( @regressions ) {
    print "$reg\n";
    @regression_links = grep(/$reg/, @current_test_summary_file );
}

但是,您每次循环都会重置@regression_linkspush会更好用:

 push @regression_links, grep(/$reg/, @current_test_summary_file );

但是,for循环无论如何都是一个糟糕的选择,因为你可能会得到重复,你可能不想要它们。由于您使用正则表达式进行匹配,因此使用多个条件的另一种方法是构建正则表达式替换。但是为了获得适当的替换,我们需要按字符串递减的长度然后按字母顺序(cmp)对其进行排序。

# create the alternation expression
my $filter 
     = join( '|'
     , sort { length( $b ) <=> length( $a ) 
            || $a cmp $b 
            } 
       @regressions 
     );
@regression_links = grep( /$filter/, @current_test_summary_file );

或者除了连接正则表达式之外,如果你想单独测试它们,更好的方法是List::MoreUtils::any

@regression_links
    = grep {
          my $c = $_; # save $_
          return any { /$c/ } @regressions;
      }  @current_test_summary_file
    ;

答案 1 :(得分:0)

Axeman是正确的,$_$reg的本地化将解决您的问题。但至于拉出比赛,我会天真地将所有比赛推到@regression_links,产生(可能)多个比赛的列表。然后,您可以使用List::MoreUtils::uniq来减少列表。如果您没有安装List :: MoreUtils,您只需复制该函数(其2行代码)。

# Axeman's changes
foreach my $reg (@regressions) {
    print "regression: $reg\n";
    # Push all matches.
    push @regression_links,  grep(/$reg/, @current_test_summary_file);
}
# Trim down the list once matching is done.
use List::MoreUtils qw/uniq/;
foreach ( uniq(@regression_links) ) {
   print "$_\n";
}