Вы повторно объявляете my $line
в своем внутреннем цикле, что означает, что оно будет равно:
if (undef =~ /$array[$x]/) {
Что, конечно, всегда будет неудачным.Если бы вы использовали use warnings
, вы бы получили ошибку:
Use of uninitialized value in pattern match (m//) at ...
, что заставляет меня подозревать, что вы не используете предупреждения, что является очень плохой идеей.
Кроме того, имейте в виду, что когда вы читаете значения в @array
, вы получите новую строку в конце, поэтому вы ищете в файле DAT строки, заканчивающиеся на \n
, которые могут не соответствовать вашим ожиданиям.,Например, если у вас есть foo\n
, он не будет совпадать с foo bar baz
.
. Решение этой проблемы заключается в chomp
ваших данных:
chomp(my @array = <TXT>);
Да, вы можете сжать массив, и вы можете назначить весь файл массиву таким образом.
Вы можете и должны немного улучшить свой скрипт.Совершенно не нужно зацикливаться с использованием индексов массива, если только вам фактически не нужно использовать индексы для чего-либо.
use strict;
use warnings; # ALWAYS use these!
use autodie; # handles the open statements for convenience
my $source = "/KEYS.txt";
my $data= "/claims.dat";
open $txt, '<', $source;
chomp(my @array = <$txt>);
close $txt;
open my $dat, '<', $data; # use three argument open and lexical file handle
open my $log, '>>', "/output.log";
while (<$dat>) { # using $_ for convenience
for my $word (@array) {
if (/\Q$word/i) { # adding /i modifier to match case insensitively
print $log $line; # also adding \Q to match literal strings
}
}
Использование \Q
может быть очень важным, в зависимости от того, что содержит ваш файл KEYS.txt.Мета-символы для регулярных выражений могут вызывать незначительные несоответствия, если вы ожидаете, что они будут совпадать буквально.Например, если у вас есть слово, такое как foo?
, регулярное выражение /foo?/
будет соответствовать foo
, но также будет соответствовать for
.
Кроме того, вы можете решить, разрешить ли частичное совпадение,Например, /foo/
также будет соответствовать football
.Чтобы преодолеть это, одним из способов является использование экранирующего символа границы слова:
/\b\Q$word\E\b/i
Вам нужно будет поместить их вне последовательности \Q .. \E
, иначе они будут интерпретироваться буквально.
ETA: Как указывает Трист и предлагает Бородин, построение регулярного выражения со всеми словами спасет вас от получения повторяющихся строк.Например, если у вас есть слова "foo"
, "bar"
и "baz"
и строка foo bar baz
, вы напечатаете эту строку три раза, по одному разу для каждого соответствующего слова.
Это может быть исправлено впоследствии путем дедупликации ваших данных подходящим способом.Только вы знаете свои данные, и является ли это проблемой или нет.Из-за производительности я бы скомпилировал такое длинное регулярное выражение, но вы можете попробовать и посмотреть, работает ли он для вас.