복붙노트

문자열에서 utf8 이외의 문자 제거

PHP

문자열에서 utf8 이외의 문자 제거

문자열에 utf8이 아닌 문자가 제대로 표시되지 않는 문제가 있습니다. 문자는 다음과 같습니다. 0x97 0x61 0x6C 0x6F (16 진수 표현)

그들을 제거하는 가장 좋은 방법은 무엇입니까? 정규 표현식인가?

해결법

  1. ==============================

    1.정규식 접근법 사용하기 :

    정규식 접근법 사용하기 :

    $regex = <<<'END'
    /
      (
        (?: [\x00-\x7F]                 # single-byte sequences   0xxxxxxx
        |   [\xC0-\xDF][\x80-\xBF]      # double-byte sequences   110xxxxx 10xxxxxx
        |   [\xE0-\xEF][\x80-\xBF]{2}   # triple-byte sequences   1110xxxx 10xxxxxx * 2
        |   [\xF0-\xF7][\x80-\xBF]{3}   # quadruple-byte sequence 11110xxx 10xxxxxx * 3 
        ){1,100}                        # ...one or more times
      )
    | .                                 # anything else
    /x
    END;
    preg_replace($regex, '$1', $text);
    

    UTF-8 시퀀스를 검색하여 그룹 1로 캡처합니다. 또한 UTF-8 시퀀스의 일부로 식별 할 수없는 단일 바이트를 일치 시키지만이를 캡처하지는 않습니다. 대체는 그룹 1에 캡처 된 모든 것입니다. 이로 인해 유효하지 않은 모든 바이트가 효과적으로 제거됩니다.

    유효하지 않은 바이트를 UTF-8 문자로 인코딩하여 문자열을 복구 할 수 있습니다. 그러나 오류가 무작위이면 일부 이상한 기호가 남을 수 있습니다.

    $regex = <<<'END'
    /
      (
        (?: [\x00-\x7F]               # single-byte sequences   0xxxxxxx
        |   [\xC0-\xDF][\x80-\xBF]    # double-byte sequences   110xxxxx 10xxxxxx
        |   [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences   1110xxxx 10xxxxxx * 2
        |   [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3 
        ){1,100}                      # ...one or more times
      )
    | ( [\x80-\xBF] )                 # invalid byte in range 10000000 - 10111111
    | ( [\xC0-\xFF] )                 # invalid byte in range 11000000 - 11111111
    /x
    END;
    function utf8replacer($captures) {
      if ($captures[1] != "") {
        // Valid byte sequence. Return unmodified.
        return $captures[1];
      }
      elseif ($captures[2] != "") {
        // Invalid byte of the form 10xxxxxx.
        // Encode as 11000010 10xxxxxx.
        return "\xC2".$captures[2];
      }
      else {
        // Invalid byte of the form 11xxxxxx.
        // Encode as 11000011 10xxxxxx.
        return "\xC3".chr(ord($captures[3])-64);
      }
    }
    preg_replace_callback($regex, "utf8replacer", $text);
    

    편집하다:

    x! = ""이 경우 사용하는 것이 가장 좋습니다.

    나는 또한 경기를 조금 더 빠르게했다. 각 문자를 개별적으로 일치시키는 대신 올바른 UTF-8 문자 시퀀스를 찾습니다.

  2. ==============================

    2.이미 UTF8 문자열에 utf8_encode ()를 적용하면 깨진 UTF8 출력이 반환됩니다.

    이미 UTF8 문자열에 utf8_encode ()를 적용하면 깨진 UTF8 출력이 반환됩니다.

    이 모든 문제를 해결하는 함수를 만들었습니다. 그것은 Encoding :: toUTF8 ()입니다.

    문자열의 인코딩이 무엇인지 알 필요가 없습니다. Latin1 (ISO8859-1), Windows-1252 또는 UTF8이 될 수도 있고 문자열이 혼합되어있을 수도 있습니다. Encoding :: toUTF8 ()은 모든 것을 UTF8로 변환합니다.

    나는 서비스가 나에게 엉망이 된 데이터 피드를주고, 같은 문자열로 인코딩을 혼합했기 때문에 그것을했다.

    용법:

    require_once('Encoding.php'); 
    use \ForceUTF8\Encoding;  // It's namespaced now.
    
    $utf8_string = Encoding::toUTF8($mixed_string);
    
    $latin1_string = Encoding::toLatin1($mixed_string);
    

    다른 함수 인 Encoding :: fixUTF8 ()을 포함 시켰습니다. UTF8로 인코딩 된 제품이 왜곡되어 보이는 모든 UTF8 문자열을 수정합니다.

    용법:

    require_once('Encoding.php'); 
    use \ForceUTF8\Encoding;  // It's namespaced now.
    
    $utf8_string = Encoding::fixUTF8($garbled_utf8_string);
    

    예 :

    echo Encoding::fixUTF8("Fédération Camerounaise de Football");
    echo Encoding::fixUTF8("Fédération Camerounaise de Football");
    echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
    echo Encoding::fixUTF8("Fédération Camerounaise de Football");
    

    출력됩니다 :

    Fédération Camerounaise de Football
    Fédération Camerounaise de Football
    Fédération Camerounaise de Football
    Fédération Camerounaise de Football
    

    다운로드 :

    https://github.com/neitanod/forceutf8

  3. ==============================

    3.mbstring을 사용할 수 있습니다.

    mbstring을 사용할 수 있습니다.

    $text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');
    

    ... 잘못된 문자가 제거됩니다.

    참고 : 유효하지 않은 UTF-8 문자를 물음표로 바꾸면 mbstring.substitute_character가 무시 된 것 같습니다.

  4. ==============================

    4.이 함수는 모든 비 ASCII 문자를 제거합니다. 유용하지만 문제를 해결하지는 못합니다 : 이것은 인코딩에 관계없이 항상 작동하는 제 기능입니다.

    이 함수는 모든 비 ASCII 문자를 제거합니다. 유용하지만 문제를 해결하지는 못합니다 : 이것은 인코딩에 관계없이 항상 작동하는 제 기능입니다.

    function remove_bs($Str) {  
      $StrArr = str_split($Str); $NewStr = '';
      foreach ($StrArr as $Char) {    
        $CharNo = ord($Char);
        if ($CharNo == 163) { $NewStr .= $Char; continue; } // keep £ 
        if ($CharNo > 31 && $CharNo < 127) {
          $NewStr .= $Char;    
        }
      }  
      return $NewStr;
    }
    

    작동 원리 :

    echo remove_bs('Hello õhowå åare youÆ?'); // Hello how are you?
    
  5. ==============================

    5.

    $text = iconv("UTF-8", "UTF-8//IGNORE", $text);
    

    이것이 제가 사용하고있는 것입니다. 꽤 잘 작동하는 것 같습니다. http://planetozh.com/blog/2005/01/remove-invalid-characters-in-utf-8/에서 가져 왔습니다.

  6. ==============================

    6.이 시도:

    이 시도:

    $string = iconv("UTF-8","UTF-8//IGNORE",$string);
    

    iconv 설명서에 따르면 함수는 첫 번째 매개 변수를 입력 charset으로 사용하고 두 번째 매개 변수는 출력 charset으로 사용하고 세 번째 매개 변수는 실제 입력 문자열로 사용합니다.

    입력 및 출력 문자 세트를 모두 UTF-8로 설정하고 출력 문자 세트에 // IGNORE 플래그를 추가하면 함수는 출력 문자 세트로 표시 할 수없는 입력 문자열의 모든 문자를 삭제 (제거)합니다. 따라서 실제로 입력 문자열을 필터링합니다.

  7. ==============================

    7.UConverter는 PHP 5.5부터 사용할 수 있습니다. int 확장을 사용하고 mbstring을 사용하지 않으면 UConverter가 가장 좋습니다.

    UConverter는 PHP 5.5부터 사용할 수 있습니다. int 확장을 사용하고 mbstring을 사용하지 않으면 UConverter가 가장 좋습니다.

    function replace_invalid_byte_sequence($str)
    {
        return UConverter::transcode($str, 'UTF-8', 'UTF-8');
    }
    
    function replace_invalid_byte_sequence2($str)
    {
        return (new UConverter('UTF-8', 'UTF-8'))->convert($str);
    }
    

    htmlspecialchars를 사용하면 PHP 5.4부터 유효하지 않은 바이트 시퀀스를 제거 할 수 있습니다. Htmlspecialchars는 큰 크기의 바이트와 정확도를 처리하기 위해 preg_match보다 낫습니다. 정규식을 사용하여 잘못된 구현을 많이 볼 수 있습니다.

    function replace_invalid_byte_sequence3($str)
    {
        return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE, 'UTF-8'));
    }
    
  8. ==============================

    8.텍스트에는 utf8이 아닌 문자가 포함될 수 있습니다. 먼저 해보십시오.

    텍스트에는 utf8이 아닌 문자가 포함될 수 있습니다. 먼저 해보십시오.

    $nonutf8 = mb_convert_encoding($nonutf8 , 'UTF-8', 'UTF-8');
    

    자세한 내용은 http://php.net/manual/en/function.mb-convert-encoding.phpnews에서 확인할 수 있습니다.

  9. ==============================

    9.문자열에서 잘못된 UTF-8 문자를 삭제하는 함수를 만들었습니다. XML 내보내기 파일을 생성하기 전에이 제품을 사용하여 27000 개 제품에 대한 설명을 정리합니다.

    문자열에서 잘못된 UTF-8 문자를 삭제하는 함수를 만들었습니다. XML 내보내기 파일을 생성하기 전에이 제품을 사용하여 27000 개 제품에 대한 설명을 정리합니다.

    public function stripInvalidXml($value) {
        $ret = "";
        $current;
        if (empty($value)) {
            return $ret;
        }
        $length = strlen($value);
        for ($i=0; $i < $length; $i++) {
            $current = ord($value{$i});
            if (($current == 0x9) || ($current == 0xA) || ($current == 0xD) || (($current >= 0x20) && ($current <= 0xD7FF)) || (($current >= 0xE000) && ($current <= 0xFFFD)) || (($current >= 0x10000) && ($current <= 0x10FFFF))) {
                    $ret .= chr($current);
            }
            else {
                $ret .= "";
            }
        }
        return $ret;
    }
    
  10. ==============================

    10.

    $string = preg_replace('~&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', '$1', htmlentities($string, ENT_COMPAT, 'UTF-8'));
    
  11. ==============================

    11.최근 패치에서 Drupal 's Feeds JSON 파서 모듈 :

    최근 패치에서 Drupal 's Feeds JSON 파서 모듈 :

    //remove everything except valid letters (from any language)
    $raw = preg_replace('/(?:\\\\u[\pL\p{Zs}])+/', '', $raw);
    

    네가 걱정된다면 공백을 유효한 문자로 유지합니다.

    내가 필요한 것을 했어. MySQL의 'utf8'문자 세트에 맞지 않는 이모티콘 문자를 제거하고 "SQLSTATE [HY000] : 일반 오류 : 1366 잘못된 문자열 값"과 같은 오류를 표시합니다.

    자세한 내용은 https://www.drupal.org/node/1824506#comment-6881382를 참조하십시오.

  12. ==============================

    12.따라서 첫 번째 UTF-8 octlet에는 마커로 설정된 높은 비트가 있고, 추가 octlet 수는 1에서 4 비트가됩니다. 추가 옥텟들 각각은 상위 2 비트가 10으로 설정되어야한다.

    따라서 첫 번째 UTF-8 octlet에는 마커로 설정된 높은 비트가 있고, 추가 octlet 수는 1에서 4 비트가됩니다. 추가 옥텟들 각각은 상위 2 비트가 10으로 설정되어야한다.

    pseudo-python은 다음과 같습니다.

    newstring = ''
    cont = 0
    for each ch in string:
      if cont:
        if (ch >> 6) != 2: # high 2 bits are 10
          # do whatever, e.g. skip it, or skip whole point, or?
        else:
          # acceptable continuation of multi-octlet char
          newstring += ch
        cont -= 1
      else:
        if (ch >> 7): # high bit set?
          c = (ch << 1) # strip the high bit marker
          while (c & 1): # while the high bit indicates another octlet
            c <<= 1
            cont += 1
            if cont > 4:
               # more than 4 octels not allowed; cope with error
          if !cont:
            # illegal, do something sensible
          newstring += ch # or whatever
    if cont:
      # last utf-8 was not terminated, cope
    

    이 동일한 논리는 php로 변환 할 수 있어야합니다. 그러나 일단 변형 된 캐릭터가 나오면 어떤 종류의 스트리핑을해야하는지 명확하지 않습니다.

  13. ==============================

    13.유니 코드 기본 언어 평면 외부의 모든 유니 코드 문자를 제거하려면 다음과 같이하십시오.

    유니 코드 기본 언어 평면 외부의 모든 유니 코드 문자를 제거하려면 다음과 같이하십시오.

    $str = preg_replace("/[^\\x00-\\xFFFF]/", "", $str);
    
  14. ==============================

    14.질문과 약간 다르지만 내가하고있는 일은 HtmlEncode (문자열)를 사용하는 것입니다.

    질문과 약간 다르지만 내가하고있는 일은 HtmlEncode (문자열)를 사용하는 것입니다.

    의사 코드는 여기에있다.

    var encoded = HtmlEncode(string);
    encoded = Regex.Replace(encoded, "&#\d+?;", "");
    var result = HtmlDecode(encoded);
    

    입력과 출력

    "Headlight\x007E Bracket, &#123; Cafe Racer<> Style, Stainless Steel 中文呢?"
    "Headlight~ Bracket, &#123; Cafe Racer<> Style, Stainless Steel 中文呢?"
    

    나는 완벽하지는 않다는 것을 알고 있지만 나를 위해 일합니다.

  15. ==============================

    15.방법에 대해 iconv :

    방법에 대해 iconv :

    http://php.net/manual/en/function.iconv.php

    PHP 자체에서는 사용하지 않았지만 항상 명령 행에서 잘 수행됩니다. 잘못된 문자를 대체 할 수 있습니다.

  16. from https://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string by cc-by-sa and MIT license