我有一个搜索字词列表,我希望有一个匹配所有至少有两个项目的正则表达式。
术语:战争|军队|战斗|反叛者|冲突匹配:反叛者与军队之间的战争导致本周发生了多次冲突。 (4次点击)
不匹配:在恐怖主义的战争中,奥巴马政府希望增加无人机袭击次数。 (只有1次点击)
背景:我使用微小的rss来收集和过滤新闻报道项目的大量信息。我每天获得1000 - 2000个Feed项,并希望按关键字过滤它们。通过使用| OR表达式,我得到了很多误报,所以我想我可以在一个feed项中要求两个匹配。
谢谢!
编辑:
我对正则表达式知之甚少,所以到目前为止我一直坚持使用简单的| OR运算符。我尝试将搜索词放在括号中(war | fight | etc){2,},但只有在项目使用相同的词两次时才匹配。
EDIT2:抱歉这是混乱,我是正则表达式之类的新手。事实是:正则表达式查询mysql数据库。它作为过滤器输入到tt-rss后端,它只允许一行(虽然理论上是无限数量的字符)。在将feed项导入mysql数据库时使用过滤器。
答案 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
}