Подсчет совпадений строк и определение того, какие совпадения предложений можно найти в - PullRequest
0 голосов
/ 31 января 2011

Я делаю это в Perl. У меня есть текстовый файл, который содержит несколько параграфов и 61 предложение. Во-первых, мне нужно сопоставить серию слов, которые вводятся в командной строке, что у меня не составит труда:

my $input = $ARGV[0];
$file =~ m/$input/gi;

К сожалению, есть некоторые морщины 1. Вход может быть для нескольких предметов и 2. Несколько элементов могут находиться в разных строках.

Я покажу вам пример: 3 предложения соответствуют шаблону «осень | выборы | 2009». Предложения:

4: «Мы ненавидим выборы». 16: «Пес был ранен при падении с балкона». 24: «Не будет осенних выборов 2009 года».

В этом случае найденная программа насчитывала три предложения в документе, который содержал либо падение, выборы или 2009 год, где вводом были осень | выборы | 2009.

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

Вторая часть моего вопроса касается того, как сначала найти, в каком предложении вводится ввод (т. Е. Выборы появляются в строке 4), и как извлечь целое предложение, в котором находится ввод. Я думаю, что это будет сделано. используя сначала if: если в строке есть совпадение с входными данными, то новый скаляр равен текстовому файлу = ~ подстановка? предложения ... Я абсолютно не уверен.

Редактировать: у меня фактически есть полностью проанализированный HTML-документ, для которого я выполняю это. Если напечатано, вывод одного примера: «Журнал теперь на Facebook! Посетите нашу страницу здесь. Он находится в стадии разработки, и мы с нетерпением ждем ваших отзывов. Поэтому дайте нам знать, что вы думаете о нашей доске обсуждений, прокомментируйте ниже или отправьте нам электронное письмо. Получить последние новости, инсайдерская информация и курьезы, следите за Журналом в Твиттере. Вот несколько новостных лент и писателей, которым вы, возможно, захотите подписаться: "

Моя командная строка выглядит следующим образом: perl WebScan.pl information | writers WebPage000.htm

Я, как уже упоминалось, проанализировал веб-страницу и удалил все теги, оставив только текст. Теперь я должен найти вход, который в данном случае является «информацией» или «писателями». Я должен выяснить, сколько раз они встречаются в тексте файла (так 2), а также в каком предложении они появляются (соответственно 5 и 6). Пока покажу свой код:

use strict;
use warnings;
my $file;
open (FILENAME, $ARGV[1]);
$file = do { local $/; <FILENAME> };

$file =~ s{
  <               # open tag
  (?:             # open group (A)
    (!--) |       #   comment (1) or
    (\?) |        #   another comment (2) or
    (?i:          #   open group (B) for /i
      (           #     one of start tags
        SCRIPT |  #     for which
        APPLET |  #     must be skipped
        OBJECT |  #     all content
        STYLE     #     to correspond
      )           #     end tag (3)
    ) |           #   close group (B), or
    ([!/A-Za-z])  #   one of these chars, remember in (4)
  )               # close group (A)
  (?(4)           # if previous case is (4)
    (?:           #   open group (C)
      (?!         #     and next is not : (D)
        [\s=]     #       \s or "="
        ["`']     #       with open quotes
      )           #     close (D)
      [^>] |      #     and not close tag or
      [\s=]       #     \s or "=" with
      `[^`]*` |   #     something in quotes ` or
      [\s=]       #     \s or "=" with
      '[^']*' |   #     something in quotes ' or
      [\s=]       #     \s or "=" with
      "[^"]*"     #     something in quotes "
    )*            #   repeat (C) 0 or more times
  |               # else (if previous case is not (4))
    .*?           #   minimum of any chars
  )               # end if previous char is (4)
  (?(1)           # if comment (1)
    (?<=--)       #   wait for "--"
  )               # end if comment (1)
  (?(2)           # if another comment (2)
    (?<=\?)       #   wait for "?"
  )               # end if another comment (2)
  (?(3)           # if one of tags-containers (3)
    </            #   wait for end
    (?i:\3)       #   of this tag
    (?:\s[^>]*)?  #   skip junk to ">"
  )               # end if (3)
  >               # tag closed
 }{}gsx;         # STRIP THIS TAG
$file =~ s/&nbsp//gi;
$file =~ s/&#160//gi;
$file =~ s/;//gi;

$file =~ s/[\h\v]+/ /g;

my $count = $file =~ s/((^|\s)\S)/$2/g;
my $sentencecount = $file =~ s/((^|\s)\S).*?(\.|\?|\!)/$1/g;

print "Input file $ARGV[1] contains $sentencecount sentences and $count words.";

Итак, мне нужен perl, чтобы, используя $ ARGV [0] в качестве ключевых слов, выполнять поиск по текстовому файлу, считая количество раз, когда ключевое слово появляется. Затем мне нужно указать, в каком предложении появилось ключевое слово (то есть напечатать все предложение полностью), а также номер, в котором находится предложение.

Ответы [ 2 ]

1 голос
/ 31 января 2011

Не ясно, если у вас есть предложения с разделителями (или если у вас есть некоторые критерии для их разделения).Если это так, и если вы правильно поняли вашу проблему, вы можете сделать что-то вроде этого:

@words = qw/hi bye 2009 a*d/;
@lines = ('Lets see , hi ',
 ' hi hi hi ',
 ' asdadasdas ',
 'a2009a',
 'hi bye');

$pattern="";
foreach $word (@words) {
    $pattern .= quotemeta($word) . '|';
}
chop $pattern; # chop last |
print "pattern='$pattern'\n";

$cont = 0;
foreach $line (@lines) {
    $cont++ if $line =~ /$pattern/o;
}

printf "$cont/%d lines matched\n",scalar(@lines);

Я создаю шаблон с quotemeta экранированием на случай, если в словах есть какие-то специальные символы (как в моемНапример, мы не хотим, чтобы это совпадало).

0 голосов
/ 31 января 2011

Изменить, чтобы соответствовать обновленному вопросу

Хорошо, позвольте мне начать с трюизма: не пытайтесь анализировать HTML самостоятельно. HTML :: TreeBuilder - ваш друг.

Для регулярных выражений perlfaq6 - отличный источник знаний.

Следующий пример работает сследующий синтаксис: perl WebScan.pl --regex="information|writers" --filename=WebPage000.htm.

Он напечатает список абзацев и их совпадений.

#!/usr/bin/perl
use warnings;
use strict;

use HTML::TreeBuilder;
use Data::Dumper;
use Getopt::Long;

my @regexes;
my $filename;
GetOptions('regex=s' => \@regexes, 'filename=s' => \$filename);

my $tb = HTML::TreeBuilder->new_from_file($filename);
$tb->normalize_content;

my @patterns = map { qr/$_/ } @regexes;

my @all;
foreach my $node ($tb->find_by_tag_name('p', 'pre', 'blockquote')) {
    my $text = $node->as_text;
    my @matches;
    foreach my $r (@patterns) {
        while ($text =~ /$r/gi) {
            push @matches, $&;
        }
    }
    push @all, { paragraph => $text, matches => \@matches } if @matches;
}

foreach (@all) {
    print "Paragraph:\n\t$_->{paragraph}\nMatches:\n\t", join(', ', @{$_->{matches}}), "\n";
}

Надеюсь, это может указать вам правильное направление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...