由于我无法使用preg_match(UTF8 支持不知何故被破坏,它在本地工作但在生产中中断),我想找到另一种将单词与黑名单匹配的方法。问题是,我只想搜索字符串以查找完全匹配项,而不是字符串的第一次出现。
这就是我用preg_match的方式
preg_match('/'b(badword)'b/', strtolower($string));
示例字符串:
$string = "This is a string containing badwords and one badword";
我只想匹配"坏词"(最后)而不是"坏词"。
strpos('badword', $string) matches the first one
有什么想法吗?
假设您可以进行一些预处理,则可以将所有标点符号替换为空格,并将所有内容都设置为小写,然后:
- 将
strpos
与类似的东西一起使用,以便在一段时间循环中strpos(' badword ', $string)
继续迭代整个文档;
在 - 空格处拆分字符串,并将每个单词与您拥有的坏单词列表进行比较。
因此,如果您在尝试第一个选项的地方,它将是这样的(未经测试的伪代码)
$documet = body of text to process . ' '
$document.replace('!@#$%^&*(),./...', ' ')
$document.toLowerCase()
$arr_badWords = [...]
foreach($word in badwords)
{
$badwordIndex = strpos(' ' . $word . ' ', $document)
while(!badWordIndex)
{
//
$badwordIndex = strpos($word, $document)
}
}
编辑:根据@jonhopkins建议,在末尾添加一个空格应该满足以下情况:文档末尾有想要的单词并且没有标点符号。
如果你想
模仿正则表达式的'b
修饰符,你可以尝试这样的事情:
$offset = 0;
$word = 'badword';
$matched = array();
while(($pos = strpos($string, $word, $offset)) !== false) {
$leftBoundary = false;
// If is the first char, it has a boundary on the right
if ($pos === 0) {
$leftBoundary = true;
// Else, if it is on the middle of the string, we must check the previous char
} elseif ($pos > 0 && in_array($string[$pos-1], array(' ', '-',...)) {
$leftBoundary = true;
}
$rightBoundary = false;
// If is the last char, it has a boundary on the right
if ($pos === (strlen($string) - 1)) {
$rightBoundary = true;
// Else, if it is on the middle of the string, we must check the next char
} elseif ($pos < (strlen($string) - 1) && in_array($string[$pos+1], array(' ', '-',...)) {
$rightBoundary = true;
}
// If it has both boundaries, we add the index to the matched ones...
if ($leftBoundary && $rightBoundary) {
$matched[] = $pos;
}
$offset = $pos + strlen($word);
}
您可以使用
strrpos()
代替strpos
:
strrpos — 查找字符串中子字符串最后一次出现的位置
$string = "This is a string containing badwords and one badword";
var_dump(strrpos($string, 'badword'));
输出:
45
一种将单词边界与 unicode 属性一起使用的简单方法:
preg_match('/(?:^|[^pL'pN_])(badword)(?:[^pL'pN_]|$)/u', $string);
事实上,它要复杂得多,看看这里。