我在Perl中这样做。 我有一个包含几个段落和61个句子的文本文件。 首先,我需要匹配在命令行输入的一系列单词,我完全没有遇到麻烦:
my $input = $ARGV[0];
$file =~ m/$input/gi;
不幸的是,有一些皱纹 - 1.输入可以是多个项目和 2.多个项目可以在不同的行上。
我会告诉你一个例子: 3个句子匹配“秋天|选举| 2009”模式。句子是:
4:“我们讨厌选举。” 16:“狗从阳台上掉下来,受伤了。” 24:“将不会有2009秋季选举。”
在这种情况下,程序发现在包含秋季,选举或2009年的文件中计算了三个句子,其中秋季选举| 2009年是输入。
我的问题有两个: 如何计算输入出现的句子数?我对正则表达式非常缺乏经验,但我认为默认匹配会尝试匹配文件中发生的第一次出现的fall,election或2009,并且不计算每个单词的实例数和然后加起来。我有点挂在这上面,因为我完全不理解用正则表达式计算。
我的问题的第二部分涉及如何首先找到输入的句子(即第4行中出现的选举)以及如何提取输入所在的整个句子。我认为这样做首先使用if:如果字符串中的输入与输入匹配则新标量等于文本文件=〜替换?这句话......我完全不确定。
编辑:我实际上有一个完全解析的HTML文档,我正在执行此操作。如果打印,一个例子的输出是: “The Journal现在在Facebook上!在这里查看我们的页面。这是一项正在进行中的工作,我们很想收到您的反馈意见。请在我们的讨论区告诉我们您的想法,在下面发表评论或发送电子邮件给我们。通过Twitter上关注The Journal来发布新闻,内幕消息和好奇心。以下是您可能想要关注的一些供稿和作者:“
我的命令行如下所示:perl WebScan.pl信息|作者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/ //gi;
$file =~ s/ //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]作为关键字,搜索文本文件,计算关键字出现的次数。然后,我需要说明关键字出现在哪个句子中(即完整地打印整个句子),以及句子所在的数字。
答案 0 :(得分:1)
目前尚不清楚你的句子是否有界限(或者你是否有一些分裂标准)。如果是这样,如果理解你的问题,你可以这样做:
@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
转义构建模式以防万一(如我的例子中,我们不希望它匹配)。
答案 1 :(得分:-1)
修改以匹配更新的问题
好吧,让我从一个真理开始:不要试图自己解析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";
}
希望这可以指出你正确的方向。