regex 屏蔽除第一个字母以外的所有不好的单词

pqwbnv8z  于 2023-05-30  发布在  其他
关注(0)|答案(5)|浏览(115)

我试图在PHP中创建一个坏词过滤器,它将搜索文本,与已知坏词的数组进行匹配,然后用星号替换坏词中的每个字符(第一个字母除外)。
示例:

  • fook将变为f***
  • shoot将变为s****

我唯一不知道的部分是如何保持字符串中的第一个字母,以及如何在保持相同字符串长度的情况下用其他字母替换其余字母。
我的代码不合适,因为它总是用3个星号替换整个单词。

$string = preg_replace("/\b(". $word .")\b/i", "***", $string);
dpiehjr4

dpiehjr41#

$string = 'fook would become';
$word = 'fook';

$string = preg_replace("~\b". preg_quote($word, '~') ."\b~i", $word[0] . str_repeat('*', strlen($word) - 1), $string);

var_dump($string);
chhqkbe1

chhqkbe12#

这可以通过许多方式来完成,使用非常奇怪的自动生成的regexp...但我相信使用preg_replace_callback()最终会更 * 健壮 *

<?php
# as already pointed out, your words *may* need sanitization

foreach($words as $k=>$v)
  $words[$k]=preg_quote($v,'/');

# and to be collapsed into a **big regexpy goodness**
$words=implode('|',$words);

# after that, a single preg_replace_callback() would do

$string = preg_replace_callback('/\b('. $words .')\b/i', "my_beloved_callback", $string);

function my_beloved_callback($m)
{
  $len=strlen($m[1])-1;

  return $m[1][0].str_repeat('*',$len);
}
31moq8wy

31moq8wy3#

$string = preg_replace("/\b".$word[0].'('.substr($word, 1).")\b/i", "***", $string);
snvhrwxg

snvhrwxg4#

假设要屏蔽的坏单词黑名单完全由字母或至少由单词字符(允许数字和下划线)组成,则在内爆和插入正则表达式模式之前不需要调用preg_quote()
在匹配到限定单词的第一个字母后,使用\G元字符继续匹配。坏单词中的每个随后匹配的字母将被星号1对1替换。
\K用于忘记/释放坏单词的第一个字母。
这种方法不需要调用preg_replace_callback()来测量每个匹配的字符串,并在文本块中每个匹配坏单词的第一个字母后写入N个星号。
细分:

/                      #start of pattern delimiter
(?:                    #non-capturing group to encapsulate logic
   \b                  #position separating word character and non-word character
   (?=                 #start lookahead -- to match without consuming letters
      (?:fook|shoot)   #OR-delimited bad words
      \b               #position separating word character and non-word character
   )                   #end lookahead
   \w                  #first word character of bad word
   \K                  #forget first matched word character
   |                   #OR -- to set up \G technique
   \G(?!^)             #continue matching from previous match but not from the start of the string
)                      #end of non-capturing group
\w                     #match non-first letter of bad word
/                      #ending pattern delimiter
i                      #make pattern case-insensitive

代码:(Demo

$bad = ['fook', 'shoot'];
$pattern = '/(?:\b(?=(?:' . implode('|', $bad) . ')\b)\w\K|\G(?!^))\w/i';

echo preg_replace($pattern, '*', 'Holy fook n shoot, Batman; The Joker\'s shooting The Riddler!');
// Holy f*** n s****, Batman; The Joker's shooting The Riddler!
xhv8bpkk

xhv8bpkk5#

这里是PHP的Unicode友好的正则表达式。这个函数本身有不同的用途,但你可以从这里使用的正则表达式中得到一个想法。

function lowercase_except_first_letter($s) {
    // the following line SKIP the first character and pass it to callback func...
    // allows to keep the first letter even in words in quotes and brackets.
    // alternative regex is '/(?<!^|\s|\W)(\w)/u'.
    return preg_replace_callback('/(\B\w)/u', function($m) {
            return mb_strtolower($m[1]);
        }, $s);
}

相关问题