programing

PHP 욕설 필터

batch 2023. 3. 17. 19:42
반응형

PHP 욕설 필터

댓글에서 나오는 나쁜 단어들을 목록에서 무작위로 새 단어들로 대체하는 WordPress 플러그인을 개발 중입니다.

이제 2개의 배열이 있습니다.하나는 나쁜 단어를 포함하는 배열이고 다른 하나는 좋은 단어를 포함하는 배열입니다.

$bad = array("bad", "words", "here");
$good = array("good", "words", "here");

저는 초보라서 어느 순간 막혔어요.

말을 ', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니', '아주머니'를 사용하고 있습니다.$newstring = str_replace($bad, $good, $string);.

에 대소문자의 감성을 끄고 싶기 때문에 이런 "bad", "Bad", "BAD", "bAd", "BAd", etc다만, 예를 들면 「Bad」라고 쓰면 「Words」로 대체되지만, 「bad」라고 입력하면 「words」 등으로 대체되는 등, 원래의 단어의 형식을 유지하기 위해서 새로운 단어가 필요합니다.

나의 첫 번째 고충은 이 제품을 사용하는 것이었다.str_ireplace그러나 원래 단어가 대문자를 사용했는지 잊어버립니다.

두 번째 문제는 "b a d", "w o r d s" 등의 사용자를 어떻게 처리해야 할지 모른다는 것입니다.아이디어가 필요해

무작위로 하게 하기 저는 '어느 정도인지', '어느 정도인지', '어느 정도인지'를 쓰면 될 것 같아요.$new = $good[rand(0, count($good)-1)];$newstring = str_replace($bad, $new, $string);더 좋은 생각이 있으면 들어볼게요

내 스크립트의 전체적인 모양:

function noswear($string)
{
    if ($string)
    {       
        $bad = array("bad", "words");
        $good = array("good", "words"); 
        $newstring = str_replace($bad, $good, $string);     
        return $newstring;
}

echo noswear("I see bad words coming!");

잘 부탁드립니다!

전구체

이러한 기능을 실장함으로써 고객 및/또는 고객님의 코드에 (여러 차례 지적된 바와 같이) 구멍이 뚫려 있습니다.예를 들어, 몇 가지 예를 들어 다음과 같습니다.

  1. 사람들은 필터를 속이기 위해 문자를 추가합니다.
  2. 사람들은 창의적이 된다(예: 빈정거림)
  3. 사람들은 수동적인 공격과 비꼬는 말을 사용할 것이다.
  4. 사람들은 단어뿐만 아니라 문장/구문을 사용한다.

모델레이트/플래깅 시스템을 구현하면 사용자가 악의적인 코멘트에 플래그를 달아 편집/삭제할 수 있습니다.

그 양해하에, 우리 진행합시다...

솔루션

다음과 같은 경우:

  1. 목록이 있다.$bad_words
  2. 목록을 가지다$good_words
  3. 대소문자를 불문하고 나쁜 을 대체하고 싶다
  4. 나쁜 말을 아무렇게나 좋은 로 대체하고 싶다
  5. 올바르게 이스케이프된 잘못된 단어 목록이 있습니다.http://php.net/preg_quote 를 참조하십시오.

쓸 수 요.PHPs preg_replace_callback★★★★

$input_string = 'This Could be interesting but should it be? Perhaps this \'would\' work; or couldn\'t it?';

$bad_words  = array('could', 'would', 'should');
$good_words = array('might', 'will');

function replace_words($matches){
    global $good_words;
    return $matches[1].$good_words[rand(0, count($good_words)-1)].$matches[3];
}

echo preg_replace_callback('/(^|\b|\s)('.implode('|', $bad_words).')(\b|\s|$)/i', 'replace_words', $input_string);

라는 거죠?preg_replace_callback모든 나쁜 단어로 구성된 정규식 패턴을 컴파일하는 거죠일치하는 형식은 다음과 같습니다.

/(START OR WORD_BOUNDARY OR WHITE_SPACE)(BAD_WORD)(WORD_BOUNDARY OR WHITE_SPACE OR END)/i

i하지 않기 에 둘 다 대소문자를 구분하지 않습니다.bad ★★★★★★★★★★★★★★★★★」Bad치합니니다다

★★replace_words그런 다음 일치하는 단어와 그 경계(공백 또는 공백 문자)를 가져와 경계와 임의의 좋은 단어로 대체합니다.

global $good_words; <-- Makes the $good_words variable accessible from within the function
$matches[1] <-- The word boundary before the matched word
$matches[3] <-- The word boundary after  the matched word
$good_words[rand(0, count($good_words)-1] <-- Selects a random good word from $good_words

어나니머스 함수

의 라이너로 할 수 .preg_replace_callback

echo preg_replace_callback(
        '/(^|\b|\s)('.implode('|', $bad_words).')(\b|\s|$)/i',
        function ($matches) use ($good_words){
            return $matches[1].$good_words[rand(0, count($good_words)-1)].$matches[3];
        },
        $input_string
    );

함수 래퍼

여러 번 사용하는 경우에는 자급자족 함수로 쓸 수도 있습니다.단, 이 경우 좋은 단어와 나쁜 단어를 호출할 때 함수에 삽입하고 싶을 가능성이 높지만(또는 영구적인 하드 코드화), 이는 어떻게 도출하느냐에 따라 달라집니다.

function clean_string($input_string, $bad_words, $good_words){
    return preg_replace_callback(
        '/(^|\b|\s)('.implode('|', $bad_words).')(\b|\s|$)/i',
        function ($matches) use ($good_words){
            return $matches[1].$good_words[rand(0, count($good_words)-1)].$matches[3];
        },
        $input_string
    );
}

echo clean_string($input_string, $bad_words, $good_words);

산출량

첫 번째 예에 나타난 입력 목록과 단어 목록을 사용하여 위의 기능을 연속적으로 수행합니다.

This will be interesting but might it be? Perhaps this 'will' work; or couldn't it?
This might be interesting but might it be? Perhaps this 'might' work; or couldn't it?
This might be interesting but will it be? Perhaps this 'will' work; or couldn't it?

물론 대체 단어는 무작위로 선택되기 때문에 페이지를 새로 고치면 다른 것을 얻을 수 있습니다.단, 이것은 교환/교환되지 않는 것을 나타냅니다.

N.B.

(에스케이프)$bad_words

foreach($bad_words as $key=>$word){
    $bad_words[$key] = preg_quote($word);
}

경계 어어 word word\b

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.\b,\s , , , , 입니다.^ ★★★★★★★★★★★★★★★★★」$단어 경계로서 여기에는 충분한 이유가 있습니다.한편, 「 」는, 「 」, 「 」의 사이에white space,start of string , , , , 입니다.end of string됩니다.\b모든 경우에 일치하는 것은 아닙니다.하다

\b\$h1t\b <---Will not match

그 이유는\b문자와 단어 이외의 문자).[^a-zA-Z0-9] ) 。$단어 문자로 계산하지 마세요.

기타

단어 목록의 크기에 따라 몇 가지 딸꾹질이 발생할 수 있습니다.시스템 설계의 관점에서 보면 일반적으로 다음과 같은 몇 가지 이유로 큰 정규식을 갖는 은 좋지 않습니다.

  1. 유지보수가 어려울 수 있습니다.
  2. 읽기/이해하기 어렵다
  3. 오류를 찾는 것은 어렵다
  4. 목록이 너무 크면 메모리 사용량이 많을 수 있습니다.

이 regex에 되는 을 전제로 .PHP첫 번째 이유는 부정입니다.두 번째도 부정해야 합니다.만약 당신이 각 나쁜 단어들을 12개씩 배열하여 단어 목록이 크다면, 나는 당신이 멈추고 당신의 접근 방식을 재고할 것을 제안합니다(읽기: 플래깅/절제 시스템을 사용).

명확하게 말하면, 특정의 expective를 필터링 하는 은 문제가 되지 않습니다.즉, 유저가 서로 격발하는 것을 막기 위해서입니다.순열을 포함한 너무 많은 것을 필터링 하려고 하면 문제가 발생합니다.일반적인 욕설 필터링을 계속하고 그것이 효과가 없다면 마지막으로 플래깅/절제 시스템을 구현하십시오.

이 방법을 생각해 냈는데 잘 되고 있어요.엔트리에 나쁜 단어가 입력되어 있는 경우 true를 반환합니다.

예:

function badWordsFilter($inputWord) {
  $badWords = Array("bad","words","here");
  for($i=0;$i<count($badWords);$i++) {
     if($badWords[$i] == strtolower($inputWord))
        return true;
     }
  return false;
}

사용방법:

if (badWordsFilter("bad")) {
    echo "Bad word was found";
} else {
    echo "No bad words detected";
}

'bad'라는 단어가 블랙리스트에 오르면 울릴 것이다.

온라인 예 1

편집 1:

remove가 제공하는 바와 같이 간단한 작업도 가능합니다.in_array체크:

function badWordsFilter($inputWord) {
  $badWords = Array("bad","words","here");
     if(in_array(strtolower($inputWord), $badWords) ) {
        return true;
     }
  return false;
}

온라인 예 2

편집 2:

약속대로, 질문에서 말씀하신 것처럼 나쁜 말을 좋은 말로 대체한다는 조금 다른 생각을 하게 되었습니다.조금 도움이 되었으면 합니다만, 지금으로서는 이것이 최선입니다.왜냐하면 당신이 무엇을 하려고 하는지 전혀 알 수 없기 때문입니다.

예:

1. 나쁜 말과 좋은 말을 가진 배열을 하나로 결합합니다.

$wordsTransform = array(
  'shit' => 'ship'
);

2. 상상의 사용자 입력

$string = "Rolling In The Deep by Adel\n
\n
There's a fire starting in my heart\n
Reaching a fever pitch, and it's bringing me out the dark\n
Finally I can see you crystal clear\n
Go ahead and sell me out and I'll lay your shit bare";

3. 나쁜 말을 좋은 말로 대체하다

$string = strtr($string, $wordsTransform);

4. 원하는 출력 얻기

롤 인 더 딥

내 심장에 불이 붙었어
열기가 극에 달하고, 그게 날 어둠에서 나오게 해
마침내 난 널 선명하게 볼 수 있어
어서 날 팔아넘기면 배를 내놓겠다

온라인 예 3

편집 3:

Wrikken의 정확한 코멘트를 따르기 위해, 나는 그것을 완전히 잊고 있었다.strtr대소문자를 구분하기 때문에 단어 검색어를 따라하는 것이 좋습니다.나는 다음 예를 에서 빌렸다.
PHP: strr - 수동으로 약간 수정했습니다.

두 번째 편집과 동일하지만 레지스터에 의존하지 않고 단어 경계를 확인하고 정규 표현 구문의 일부인 모든 문자 앞에 백슬래시를 배치합니다.

1. 방법:

//
// Written by Patrick Rauchfuss
class String
{
    public static function stritr(&$string, $from, $to = NULL)
    {
        if(is_string($from))
            $string = preg_replace("/\b{$from}\b/i", $to, $string);

        else if(is_array($from))
        {
            foreach ($from as $key => $val)
                self::stritr($string, $key, $val);
        }
        return preg_quote($string); // return and add a backslash to special characters
    }
}

2. 나쁜 말과 좋은 말을 가진 배열

$wordsTransform = array(
            'shit' => 'ship'
        );

3. 교환

String::stritr($string, $wordsTransform);

온라인 예 4

언급URL : https://stackoverflow.com/questions/19358774/php-swear-word-filter

반응형