【发布时间】:2015-09-18 01:14:08
【问题描述】:
首先,感谢您在这个问题上给我的任何帮助。我有一个单词列表,在下面的示例中它是一个颜色列表。我们称之为 WORD_LIST_1。 我想计算每个单词出现在正文中的次数。我可以用一个简单的正则表达式来做到这一点。 但是,我有另一个捕获上下文的单词列表。在下面的示例中,上下文是宠物列表。我们称之为 WORD_LIST_2。 我想计算 WORD_LIST_1 中每个单词在 WORK_LIST_2 中任何单词的 X 个单词内的次数。 我的策略是使用正则表达式将 WORD_LIST_1 单词的匹配项提取到一个数组中,然后创建计算每个单词在该数组中的次数的哈希。 当上下文词 (WORD_LIST_2) 跟随 WORD_LIST_1 词时,我可以轻松做到。 但是,当 WORD_LIST_2 单词出现在 WORD_LIST_1 单词之前时,我遇到了问题,特别是当有多个 WORD_LIST_2 单词时。
下面是代码。
#!/usr/bin/perl -w
#use strict;
@colors = ("red", "blue", "green", "brown");
$WORD_LIST_1 = join("|",@colors);
@pets = ("cat","dog","bird","fish");
$WORD_LIST_2 = join("|",@pets);
#$text1 = "The red haired dog quickly and sharply ran away from the blue nosed cat.";
#$text1 = "The green spotted cat drinks blue water.";
#$text1 = "The brown feathered, green beaked bird flew away.";
$text1 = "The fish with blue fins and red tails.";
@finds = ();
$within_N_words = 4;
@finds = $text1 =~ m/\b(?=($WORD_LIST_1)\W+(?:\w+\W+){0,$within_N_words}?(?:$WORD_LIST_2))\b|\b(?=(?:$WORD_LIST_2)\W+(?:\w+\W+){0,$within_N_words}?($WORD_LIST_1))\b/gi;
@finds = grep defined, @finds;
print "\n\n", join("|", @finds), "\n\n";
请注意,第四行 $text1 后面有蓝色和红色的鱼。但它只返回“蓝色”,也不返回“红色”。我检查了前三个被注释掉的句子,它们似乎运行良好。
我的方法是基于这个页面:http://www.regular-expressions.info/near.html
我考虑过的想法包括使用积极的后视,但我需要在后视中使用可变长度。
我考虑过反转整个文本字符串和正则表达式,然后再次搜索。但这可能会导致重复计算。
我还考虑过使用某种循环在单个常规 expersions 中搜索每个 WORD_LIST_1 单词。 但是,这需要花费大量时间处理我的真实数据,因为实际的 WORD_LIST_1 列表大约有 500 个单词,而且我有多个要搜索的长度文本。
另外两个旁注:
(1) 上面的正则表达式偶尔会在@finds 数组中返回空元素。我不知道为什么。我的解决方法是使用 grep 定义的行。解决这个问题的正确方法是什么。相反,为什么我的正则表达式返回空白元素?
(2) 我仍在学习使用 PERL 的“正确”方法。我在这个例子中注释掉了 use strict ,因为我不相信在我使用 perl 的上下文中它会有所作为。我相信有人可以告诉我为什么这是我的错。优秀的 PERL 程序员似乎总是告诉我,我不应该在不使用 strict 的情况下运行 perl 代码,但还没有人说服我这是我需要担心的事情。但是,我愿意学习。
【问题讨论】:
-
我不太确定正则表达式真的是这项工作的工具。充其量你最终会得到一些极其复杂的语法 - 正如你所发现的那样 - 真的很难解开。
-
另外:你为什么不相信优秀程序员的意见?普遍的观点是 -
strict和warnings应该是您的第一个故障排除步骤,因为它们会突出一些“有效”但不会产生预期结果的错误。