Unicode preg_将关键字变量与本地UTF-8编码文件中的拉丁和非拉丁字符关键字列表进行匹配
我有一个坏词过滤器,它使用保存在本地UTF-8编码文件中的关键字列表。该文件包括拉丁和非拉丁字符(主要是英语和阿拉伯语)。对于拉丁关键字,一切都按预期进行,但当变量包含非拉丁字符时,匹配似乎无法识别这些现有关键字Unicode preg_将关键字变量与本地UTF-8编码文件中的拉丁和非拉丁字符关键字列表进行匹配,unicode,filter,matching,multibyte,non-latin,Unicode,Filter,Matching,Multibyte,Non Latin,我有一个坏词过滤器,它使用保存在本地UTF-8编码文件中的关键字列表。该文件包括拉丁和非拉丁字符(主要是英语和阿拉伯语)。对于拉丁关键字,一切都按预期进行,但当变量包含非拉丁字符时,匹配似乎无法识别这些现有关键字 $badwords = file_get_contents("badwords.txt"); $badtemp = explode("\n", $badwords); $badwords = array_unique($badtemp); $hasBadword = 0; $que
如何匹配拉丁语和非拉丁语关键字 如本例所示,badwords.txt文件每行包含一个单词$badwords = file_get_contents("badwords.txt"); $badtemp = explode("\n", $badwords); $badwords = array_unique($badtemp); $hasBadword = 0; $query = strtolower($query); foreach ($badwords as $key => $val) { if (!empty($val)) { $val = trim($val); $regexp = "/\b" . $val . "\b/i"; if (preg_match($regexp, $query)) $badFlag = 1; if ($badFlag == 1) { // Bad word detected die... } } }
用于匹配的代码:
我读过iconv、多字节函数(mbstring)和使用运算符/u可能会有帮助,我尝试了一些方法,但似乎没有成功。如果您能帮助解决这个问题,并让它同时匹配拉丁语和非拉丁语关键字,我们将不胜感激。PHP中的一些字符串函数不能用于UTF-8字符串,它们应该会在版本6中修复它,但现在您需要小心处理字符串 看起来就是其中之一,您需要使用strtolower()
。如果这不能解决问题,您需要通读代码,找到处理mb\u strtolower($query,'UTF-8')
或$query
的每个点,并检查文档中是否存在UTF-8错误 据我所知,badwords.txt
可以使用UTF-8字符串,但默认情况下会禁用一些功能以提高性能。我想你不需要它们 请再次检查preg_match()
是否为UTF-8文件,以及badwords.txt
是否包含有效的UTF-8字符串(如果它来自浏览器,则使用$query
标记进行设置) 如果您试图调试UTF-8文本,请记住,大多数web浏览器都不会默认使用UTF-8文本编码,因此,除非您选择UTF-8(在我的浏览器中,使用),否则您为调试而打印的任何PHP变量都不会被浏览器正确显示查看->编码->Unicode
您不需要使用或任何其他转换API,它们中的大多数将简单地用拉丁字符替换所有非拉丁字符。显然不是你想要的。这个问题似乎与识别单词边界有关;\b构造显然不是“Unicode感知的”。这就是问题的答案所暗示的。当使用\b时,即使文本中包含像“é”这样的拉丁字母,我也能重现这个问题。当我设置时,问题似乎消失了(也就是说,阿拉伯语单词被正确识别)iconv
并修改regexp,如下所示:$regexp = "/" . $wstart . $val . $wend . "/iu";
谢谢阿比的回复。文件确实是使用UTF-8保存的,查询来自使用meta charset=UTF-8的UTF-8编码页面”。我以前使用过mb_strtolower()和mb_ereg_match()它仍然匹配英语关键字,但不匹配阿拉伯语。这与浏览器默认语言无关,只是为了匹配badwords.txt文件中存在的查询关键字,然后进行进一步处理,所有演示页面都是UTF-8编码的页面。如果有任何进一步的想法,我们将不胜感激。谢谢你,这正是我们想要的我需要,它终于起作用了。我不会想到问题会是它原来的样子。在我测试各种建议时,边界regexp实际上一直保持不变。非常感谢。$wstart = '(^|[^\p{L}])'; $wend = '([^\p{L}]|$)';
$regexp = "/" . $wstart . $val . $wend . "/iu";