Да, я представляю, что вы там делаете очень медленно, хотя по нескольким причинам. Я думаю, вам нужно обработать регулярное выражение стоп-слов до того, как вы соберете свою строку из миллиарда слов из вашего корпуса.
Я понятия не имею, что такое файл .regex, но я собираюсь предположить, что он содержит допустимое регулярное выражение Perl, то, что вы можете скомпилировать, используя не более:
$stopword_string = `cat foo.regex`;
$stopword_rx = qr/$stopword_string/;
Это, вероятно, предполагает, что в начале есть (?x)
.
Но если ваш файл стоп-слов представляет собой список строк, вам нужно будет сделать что-то более похожее на это:
chomp(@stopwords = `cat foo.regex`);
# if each stopword is an independent regex:
$stopword_string = join "|" => @stopwords;
# else if each stopword is a literal
$stopword_string = join "|" => map {quotemeta} @stopwords;
# now compile it (maybe add some qr//OPTS)
$stopword_rx = qr/\b(?:$stopword_string)\b/;
ПРЕДУПРЕЖДЕНИЕ
Будьте очень осторожнее с \b
: он будет делать то, что, как вы думаете, он сделает выше, только если первый символ в первом слове и последний символ в последнем слове - буквенное число (a \w
символ). В противном случае это будет утверждение чего-то, что вы, вероятно, не имеете в виду. Если это возможно, вам нужно быть более конкретным. Ведущий \b
должен стать (?:(?<=\A)|(?<=\s))
, а трейлинг \b
должен стать (?=\s|\z)
. Это то, что большинство людей считают \b
, но на самом деле это не так.
Сделав это, вы должны применить регулярное выражение стоп-слова к корпусу, когда вы читаете его. Лучший способ сделать это - , а не , чтобы поместить материал в строку в первую очередь, вам просто нужно вынуть позже.
Так что вместо того, чтобы делать
$corpus_text = `cat some-giant-file`;
$corpus_text =~ s/$stopword_rx//g;
Вместо этого
my $corpus_path = "/some/path/goes/here";
open(my $corpus_fh, "< :encoding(UTF-8)", $corpus_path)
|| die "$0: couldn't open $corpus_path: $!";
my $corpus_text = q##;
while (<$corpus_fh>) {
chomp; # or not
$corpus_text .= $_ unless /$stopword_rx/;
}
close($corpus_fh)
|| die "$0: couldn't close $corpus_path: $!";
Это будет намного быстрее, чем положить туда вещи, которые вам просто придется позже отсеять.
Мое использование cat
выше просто ярлык. Я не ожидаю, что вы на самом деле будете вызывать программу, в меньшей степени cat
, просто для чтения в одном файле, необработанном и беспрепятственном. ☺