正则表达式:匹配至少两个搜索词

时间:2012-05-31 11:14:58

标签: regex search

我有一个搜索字词列表,我希望有一个匹配所有至少有两个项目的正则表达式。

术语:战争|军队|战斗|反叛者|冲突

匹配:反叛者军队之间的战争导致本周发生了多次冲突。 (4次点击)

不匹配:在恐怖主义的战争中,奥巴马政府希望增加无人机袭击次数。 (只有1次点击)

背景:我使用微小的rss来收集和过滤新闻报道项目的大量信息。我每天获得1000 - 2000个Feed项,并希望按关键字过滤它们。通过使用| OR表达式,我得到了很多误报,所以我想我可以在一个feed项中要求两个匹配。

谢谢!

编辑:

我对正则表达式知之甚少,所以到目前为止我一直坚持使用简单的| OR运算符。我尝试将搜索词放在括号中(war | fight | etc){2,},但只有在项目使用相同的词两次时才匹配。

EDIT2:抱歉这是混乱,我是正则表达式之类的新手。事实是:正则表达式查询mysql数据库。它作为过滤器输入到tt-rss后端,它只允许一行(虽然理论上是无限数量的字符)。在将feed项导入mysql数据库时使用过滤器。

4 个答案:

答案 0 :(得分:7)

(.*?\b(war|army|fighting|rebels|clashes)\b){2,}

如果您需要避免匹配相同的术语,可以使用:

.*?\b(war|army|fighting|rebels|clashes).*?(\b(?!\1)(war|army|fighting|rebels|clashes)\b)

匹配一个术语,但避免使用否定前瞻再次匹配相同的术语。

在java中:

Pattern multiword = Pattern.compile(
    ".*?(\\b(war|army|fighting|rebels|clashes)\\b)" +
    ".*?(\\b(?!\\1)(war|army|fighting|rebels|clashes)\\b)"
);
Matcher m;
for(String str : Arrays.asList(
        "war",
        "war war war",
        "warm farmy people",
        "In the war on terror rebels eating faces"

)) {
    m = multiword.matcher(str);
    if(m.find()) {
        logger.info(str + " : " + m.group(0));
    } else {
        logger.info(str + " : no match.");
    }
}

打印:

war : no match.
war war war : no match.
warm farmy people : no match.
In the war on terror rebels eating faces : In the war on terror rebels

答案 1 :(得分:1)

这不是(完全)正则表达式的工作。更好的方法是扫描文本,然后计算唯一的匹配组。

在Ruby中,根据您的匹配计数进行分支会非常简单。例如:

terms = /war|army|fighting|rebels|clashes/
text = "The war between the rebels and the army resulted in..."

# The real magic happens here.
match = text.scan(terms).uniq

# Do something if your minimum match count is met.
if match.count >= 2
  p match
end

这将打印["war", "rebels", "army"]

答案 2 :(得分:0)

正则表达式可以解决问题,但正则表达式会非常庞大​​。

请记住,它们是简单的工具(基于有限状态自动机),因此没有任何记忆可以让他们记住已经看过的单词。因此,即使可能,这样的正则表达式可能只是看起来像一个巨大的或一样(对于每个可能的输入顺序或其他东西,一个“或”)。

我建议您自己进行解析,例如:

var searchTerms = set(yourWords);
int found = 0;
foreach (var x in words(input)) {
    if (x in searchTerms) {
        searchTerms.remove(x);
        ++found;
    }
    if (found >= 2) return true;
}
return false;

答案 3 :(得分:0)

如果你想用正则表达式做这一切,那就不太容易了。

你可以这样做:

<?php
...
$string = "The war between the rebels and the army resulted in several clashes this week. (4 hits)";


preg_match_all("@(\b(war|army|fighting|rebels|clashes))\b@", $string, $matches);
$uniqueMatchingWords = array_unique($matches[0]);
if (count($uniqueMatchingWords) >= 2) {
    //bingo
}