7

我要疯了,试图让一个正则表达式来检测用户输入中的关键字垃圾邮件。通常在开头有一些普通文本,在结尾有关键字 spam,用逗号或其他字符分隔。

我需要的是一个正则表达式来计算关键字的数量以标记文本以供人类检查。

文字通常是这样的:

[random text, with commas, dots and all]

keyword1, keyword2, keyword3, keyword4, keyword5,
Keyword6, keyword7, keyword8...

我已经尝试了几个正则表达式来计算匹配:

- 这只能得到两个关键字中的一个

[,-](\w|\s)+[,-]

- 这也匹配随机文本

(?:([^,-]*)(?:[^,-]|$))

谁能告诉我一个正则表达式来做到这一点?还是我应该采取不同的方法?

谢谢!

4

6 回答 6

13

公关您对我的问题的回答,这是一个匹配出现在两个逗号之间的字符串的正则表达式。

(?<=,)[^,]+(?=,)

此正则表达式不匹配,因此不使用分隔逗号。此正则表达式将匹配上一句中的“因此不消耗”。

您的正则表达式匹配并使用逗号的事实是您尝试的正则表达式仅匹配所有其他候选人的原因。

此外,如果整个输入是单个字符串,您将需要防止换行符。在这种情况下,您将要使用;

(?<=,)[^,\n]+(?=,)

http://www.phpliveregex.com/p/1DJ

于 2013-10-22T08:44:35.143 回答
3

正如其他人所说,这可能是一件非常棘手的事情......它遭受与一般“单词过滤”相同的所有失败(例如,人们会“掩盖”输入)。如果没有大量示例帖子进行测试,这将变得更加困难......

解决方案

无论如何,假设关键字将位于输入的其余部分的不同行并用逗号分隔,您可以将这些行与关键字匹配,如下所示:

正则表达式

#(?:^)((?:(?:[\w\.]+)(?:, ?|$))+)#m

输入

摘自您上面的问题:

[随机文本,带有逗号、点和所有]

关键字 1、关键字 2、关键字 3、关键字 4、关键字 5、
关键字 6、关键字 7、关键字 8

输出

// preg_match_all('#(?:^)((?:(?:[\w]+)(?:, ?|$))+)#m', $string, $matches);
// var_dump($matches);

array(2) {
  [0]=>
  array(2) {
    [0]=>
    string(49) "keyword1, keyword2, keyword3, keyword4, keyword5,"
    [1]=>
    string(31) "Keyword6, keyword7, keyword8..."
  }
  [1]=>
  array(2) {
    [0]=>
    string(49) "keyword1, keyword2, keyword3, keyword4, keyword5,"
    [1]=>
    string(31) "Keyword6, keyword7, keyword8"
  }
}

解释

#(?:^)((?:(?:[\w]+)(?:, ?|$))+)#m
  1. #=> 起始分隔符
  2. (?:^)=> 匹配非捕获组中的行首(你可以只使用^我最初使用的|\n并且没有更新)
  3. (=> 开始一个捕获组
  4. (?:=> 开始一个非捕获组
  5. (?:[\w]+)=> 匹配一个或多个单词字符的非捕获组a-zA-Z0-9_(使用字符类,以便您可以在需要时添加到它......)
  6. (?:, ?|$)=> 匹配逗号(带有可选空格)或字符串/行结尾的非捕获组
  7. )+=> 结束非捕获组 (4) 并重复 5/6 以在该行中找到多个匹配项
  8. )=> 关闭捕获组 3
  9. #=> 结束分隔符
  10. m=> 多行修饰符

从 2 号开始跟进:

#^((?:(?:[\w]+)(?:, ?|$))+)#m

计算关键字

现在返回了一个只包含关键字的行数组,您可以计算逗号的数量,从而获得关键字的数量

$key_words = implode(', ', $matches[1]); // Join lines returned by preg_match_all
echo substr_count($key_words, ',');      // 8

注意在大多数情况下,这将返回NUMBER_OF_KEY_WORDS - 1(即在您的情况下为 7);它返回8是因为您在第一行关键字的末尾有一个逗号。


链接

http://php.net/manual/en/reference.pcre.pattern.modifiers.php
http://www.regular-expressions.info/
http://php.net/substr_count

于 2013-10-22T09:22:21.687 回答
1

为什么不只使用爆炸和修剪?

$keywords = array_map ('trim', explode (',', $keywordstring));

然后对 $keywords 执行 count()。

如果您认为带有空格的关键字是垃圾邮件,那么您可以迭代 $keywords 数组并查找任何包含空格的关键字。不过,在关键字中包含空格可能是有正当理由的。例如,如果您在谈论系统上的超级英雄,有人可能会输入The TickIron Man作为关键字

我不认为计算关键字和在关键字中查找空格确实是检测垃圾邮件的非常好的策略。您可能想改用其他机器人保护策略,甚至使用手动审核。

于 2013-10-22T08:25:05.187 回答
0

您的第一个正则表达式不需要前面的逗号

[\w\s]+[,-]
于 2013-10-22T08:26:28.060 回答
0

如果人们在 2021 年仍然在搜索这个

([^,\n])+

匹配除新行和逗号 regexr.com/60eme 之外的任何内容

于 2021-06-21T22:05:13.950 回答
-2

我认为困难在于随机文本也可以包含逗号。

如果关键字都在一行上并且是整个文本的最后一行,则修剪整个文本,从末尾删除换行符。然后将文本从最后一个换行符带到末尾。这应该是包含关键字的字符串。一旦你挑出这部分,你可以用逗号分解字符串并计算部分。

<?php
$string = " some gibberish, some more gibberish, and random text

keyword1, keyword2, keyword3

";

$lastEOL = strrpos(trim($string), PHP_EOL);
$keywordLine = substr($string, $lastEOL);
$keywords = explode(',', $keywordLine);

echo "Number of keywords: " . count($keywords);

我知道它不是正则表达式,但我希望它仍然有帮助。

找到解决方案的唯一方法是找到将随机文本和关键字中不存在的关键字分开的东西。如果关键字中出现新行,则不能使用它。但是是连续 2 条新线吗?或任何其他字符。

$string = " some gibberish, some more gibberish, and random text

keyword1, keyword2, keyword3,
keyword4, keyword5, keyword6,
keyword7, keyword8, keyword9

";

$lastEOL = strrpos(trim($string), PHP_EOL . PHP_EOL); // 2 end of lines after random text
$keywordLine = substr($string, $lastEOL);
$keywords = explode(',', $keywordLine);

echo "Number of keywords: " . count($keywords);

(编辑:添加了更多新行的示例 - 远射)

于 2013-10-22T08:25:28.683 回答