Добавление уникальных элементов в массив Perl, определяемый регулярным выражением

Я пишу Perl-скрипт для анализа кодов ошибок и определения того, являются ли они уникальными. Ошибка уникальна в зависимости от того, на какой линии она находится. Стандартное сообщение об ошибке может быть:

RT Warning: No condition matches in 'unique case' statement.
    "/user/foo/project", line 218, for ..

Многие из этих сообщений об ошибках имеют несколько номеров в строках, которые я собираю. Итак, что я хочу сделать, это захватить первое вхождение числа после слова "строка" и добавить его в массив ТОЛЬКО, если это значение отсутствует в массиве. Вот что у меня так далеко:

my $path = RT Warning: No condition matches in 'unique case' statement.
    "/user/foo/project", line 218
$path =~ m/(\d+)/;
print("Error occurs on line $1\n"); 
if(grep(/^$1$/, @RTarray))
{
    print("Not unique.\n");
}
else
{
    push(@RTarray, $1); 
    print("Found a unique error!\n");
}

Итак, очевидно, что я не проверяю, стоит ли это после ключевого слова "line", потому что я не совсем уверен, как это сделать, исходя из того, как я сейчас работаю с регулярным выражением. Кроме того, я не думаю, что правильно добавляю элементы в свой массив. Помогите, пожалуйста!

1 ответ

Решение

Вы должны использовать хеш для этого. В него встроена уникальность, и вам даже не нужно проверять.

Вот пример:

my %seen;

while (my $line = <$fh>) {

  if ($line =~ m/line (\d+)/) {
    my $ln = $1;
    if ( ! $seen{$ln}++ ) { 
      # this will check first and then increment. If it was encountered before,
      # it will already contain a true value, and thus the block will be skipped.
      # if it has not been encountered before, it will go into the block and...

      # do various operations on the line number
    }
  }

}

Ваш %seen теперь содержит все строки с ошибками и сколько в строке:

print Dumper \%seen:

$VAR1 = {
  10 => 1,
  255 => 5,
  1337 => 1,
}

Это говорит нам о том, что была одна ошибка в строке 10 и одна в строке 1337. Они уникальны в соответствии с вашим кодом. Пять ошибок в строке 255 не являются уникальными, поскольку они появляются пять раз в журнале.


Если вы хотите избавиться от некоторых из них, используйте delete удалить всю пару ключ / значение или $foo{$1}-- уменьшать или что-то вроде delete $foo{$1} unless --$foo{$1} уменьшить и избавиться от него в одну строку.


Изменить: я посмотрел на ваш код. На самом деле, единственное, чего не хватает, это регулярное выражение и кавычки. Вы действительно пробовали это? Оно работает.:)

my @RTarray;

while (my $line = <DATA>) {
  $line =~ m/line (\d+)/;
  print("Error occurs on line $1\n"); 
  if( grep { $_ eq $1 } @RTarray ) { # this eq is the same as your regex, just faster
    print("Not unique.\n");
  } else {
    print "Found a unique error in line $1!\n";
    push @RTarray, $1; 
  }
}

__DATA__
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 218, for
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 3, for
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 44, for
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 218, for
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 7, for
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 7, for
RT Warning: No condition matches in 'unique case' statement. "/user/foo/project", line 7, for

Это напечатает:

Error occurs on line 218
Found a unique error in line 218!
Error occurs on line 3
Found a unique error in line 3!
Error occurs on line 44
Found a unique error in line 44!
Error occurs on line 218
Not unique.
Error occurs on line 7
Found a unique error in line 7!
Error occurs on line 7
Not unique.

И я думаю, что это правильно. У меня было 218 двойных и 7 тройных, и он нашел их обоих.

Я заменил вашу строку, в которой отсутствовали кавычки, на цикл файлового дескриптора, чтобы проверить его на нескольких строках. Я также исправил ваше регулярное выражение, в котором отсутствовала строка слова, но это даже не было необходимо для этого конкретного сообщения об ошибке.

Другие вопросы по тегам