3

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

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

比赛:叛军军队之间的战争导致了本周的几次冲突。(4 次命中)

不匹配:在反恐战争中,奥巴马政府希望增加无人机袭击的次数。(仅 1 次命中)

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

谢谢!

编辑:

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

EDIT2:对不起,我是正则表达式等的新手。事实是:正则表达式查询一个 mysql 数据库。它作为过滤器输入到 tt-rss 后端,它只允许一行(尽管理论上无限数量的字符)。在将提要项目导入 mysql 数据库时使用过滤器。

4

4 回答 4

8
(.*?\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
于 2012-05-31T11:20:22.790 回答
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"].

于 2012-05-31T11:24:41.320 回答
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
}
于 2012-05-31T11:37:52.370 回答
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;
于 2012-05-31T11:21:31.253 回答