Добавление уникальных элементов в массив 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 тройных, и он нашел их обоих.
Я заменил вашу строку, в которой отсутствовали кавычки, на цикл файлового дескриптора, чтобы проверить его на нескольких строках. Я также исправил ваше регулярное выражение, в котором отсутствовала строка слова, но это даже не было необходимо для этого конкретного сообщения об ошибке.