Использование Regex / Grep для захвата строк из массива с использованием массива шаблонов - PullRequest
1 голос
/ 26 июля 2011

После поиска во всем Интернете и, будучи новичком в Perl, я решил опубликовать это решение в стеке.

Я собираюсь выполнить цикл по массиву1, содержащему требуемые совпадения (они будут отличаться каждый раз и могут содержать множество шаблонов (правильные строки, которые должны быть сопоставлены), но используя этот пример, чтобы я мог понять проблему). Затем тестируем каждый элемент с помощью grep, который использует array2, который содержит несколько строк. Затем распечатайте строки, которые 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 ]

4 голосов
/ 26 июля 2011

Внутри grep, $_ относится к элементу списка, участвующему в тесте.Кроме того, /abc/ является сокращением от $_ =~ /abc/, поэтому вы эффективно тестируете $_ =~ /$_/ угадайте, каким будет ответ (без метасимволов)?

Итак, вы передаете все значения в @regression_links.

Что вам нужно сделать, это сохранить значение $_.Но так как вы не используете простой оператор print, вы можете так же легко зарезервировать переменную $_ для grep, например:

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

Однако вы сбрасываете @regression_linksс каждым циклом, и push будет работать лучше:

 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
    ;
0 голосов
/ 27 июля 2011

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";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...