文字列からutf8以外の文字を削除すると問題が発生しますが、正しく表示されません。文字はこのような0x97 0x61 0x6C 0x6F(16進表記)
それらを削除する最良の方法は何ですか?正規表現か何か?
文字列からutf8以外の文字を削除すると問題が発生しますが、正しく表示されません。文字はこのような0x97 0x61 0x6C 0x6F(16進表記)
それらを削除する最良の方法は何ですか?正規表現か何か?
回答:
正規表現アプローチを使用する:
$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バイトに一致しますが、それらはキャプチャしません。置換は、グループ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);
編集:
!empty(x)
空でない値と一致します("0"
空と見なされます)。x != ""
を含む空でない値に一致します"0"
。x !== ""
以外のすべてに一致し""
ます。x != ""
この場合に使用するのが最善のようです。
試合も少しスピードアップしました。各文字を個別に照合する代わりに、有効なUTF-8文字のシーケンスを照合します。
$regex = <<<'END'
PHP 5.3.xの代わりに何を使用するのですか?
elseif (!empty($captures([2])) {
使用する必要があります。また、この機能は非常に遅いですが、これはより速く実行できますか?!== ""
"0"
utf8_encode()
すでにUTF8文字列に適用すると、文字化けした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
ダウンロード:
mbstringを使用できます。
$text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');
...無効な文字を削除します。
参照:無効なUTF-8文字を疑問符で置き換えると、mbstring.substitute_characterは無視されるようです
<0x1a>
<0x1a>
、印刷可能な文字ではありませんが、完全に有効なUTF-8シーケンスです。印刷できない文字で問題が発生する可能性がありますか?:このチェックstackoverflow.com/questions/1176904/...
ini_set('mbstring.substitute_character', 'none');
ました。そうしないと、結果に疑問符が付きました。
この関数はすべての非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?
í
有効なUTF-8文字である住所フィールドの文字でした表を参照してください。士気:APIエラーメッセージを信頼しない:)
$text = iconv("UTF-8", "UTF-8//IGNORE", $text);
これは私が使っているものです。かなりうまくいくようです。http://planetozh.com/blog/2005/01/remove-invalid-characters-in-utf-8/から取得
これを試して:
$string = iconv("UTF-8","UTF-8//IGNORE",$string);
iconvマニュアルによれば、関数は最初のパラメーターを入力文字セット、2番目のパラメーターを出力文字セット、3番目のパラメーターを実際の入力文字列として受け取ります。
入力文字セットと出力文字セットの両方をUTF-8に設定し、//IGNORE
フラグを出力文字セットに追加すると、関数は、出力文字セットで表すことができない入力文字列のすべての文字を削除(ストリップ)します。したがって、有効な入力文字列をフィルタリングします。
iconv
。@halfer多分あなたの入力データはutf-8からのものではありません。別のオプションは、ASCIIに再変換してから再びutf-8に戻すことです。私の場合、私は次のiconv
ように使用しました$output = iconv("UTF-8//", "ISO-8859-1//IGNORE", $input );
テキストにutf8以外の文字が含まれている可能性があります。最初にやってみてください:
$nonutf8 = mb_convert_encoding($nonutf8 , 'UTF-8', 'UTF-8');
詳しくは、http://php.net/manual/en/function.mb-convert-encoding.php newsをご覧ください。
UConverterはPHP 5.5以降で使用できます。intl拡張を使用し、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);
}
PHP 5.4以降、htmlspecialcharsを使用して無効なバイトシーケンスを削除できます。大きなサイズのバイトと精度を処理するには、Htmlspecialcharsがpreg_matchよりも優れています。正規表現を使用した多くの誤った実装が見られます。
function replace_invalid_byte_sequence3($str)
{
return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE, 'UTF-8'));
}
文字列から無効な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;
}
ord()
0から255の範囲の結果を返します。if
この関数の巨人は、ord()
決して戻らないユニコード範囲をテストします。この関数が機能する理由を誰かが明確にしたい場合は、洞察をいただければ幸いです。
2019へようこそ、/u
UTF-8マルチバイト文字を処理する正規表現の修飾子
使用するだけの場合mb_convert_encoding($value, 'UTF-8', 'UTF-8')
は、文字列に印刷不可能な文字が含まれることになります
このメソッドは:
mb_convert_encoding
\r
、\x00
(NULL-byte)のような印刷できない文字やその他の制御文字を削除します。preg_replace
function utf8_filter(string $value): string{
return preg_replace('/[^[:print:]\n]/u', '', mb_convert_encoding($value, 'UTF-8', 'UTF-8'));
}
[:print:]
すべての印刷可能な文字と\n
改行を一致させ、その他すべてを取り除きます
以下のASCIIテーブルを参照してください。印刷可能な文字の範囲は32〜127 \n
ですが、改行は0〜31の範囲の制御文字の一部であるため、正規表現に改行を追加する必要があります。/[^[:print:]\n]/u
\x7F
(DEL)、\x1B
(Esc)などの印刷可能な範囲外の文字を含む正規表現を介して文字列を送信して、それらがどのように削除されるかを確認できます。
function utf8_filter(string $value): string{
return preg_replace('/[^[:print:]\n]/u', '', mb_convert_encoding($value, 'UTF-8', 'UTF-8'));
}
$arr = [
'Danish chars' => 'Hello from Denmark with æøå',
'Non-printable chars' => "\x7FHello with invalid chars\r \x00"
];
foreach($arr as $k => $v){
echo "$k:\n---------\n";
$len = strlen($v);
echo "$v\n(".$len.")\n";
$strip = utf8_decode(utf8_filter(utf8_encode($v)));
$strip_len = strlen($strip);
echo $strip."\n(".$strip_len.")\n\n";
echo "Chars removed: ".($len - $strip_len)."\n\n\n";
}
php-mbstring
。デフォルトではphpにパックされていません。
$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'));
最近のパッチからDrupalの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を参照してください
iconv
は、昔ながらの正規表現ベースのものよりもはるかに優れており、preg_replace
現在では非推奨です。
ereg_replace()
、申し訳ありません。
おそらく最も正確な解決策ではないかもしれませんが、1行のコードで作業を完了できます。
echo str_replace("?","",(utf8_decode($str)));
utf8_decode
文字を疑問符に変換します。
str_replace
疑問符が取り除かれます。
したがって、ルールは、最初のUTF-8オクレットにハイビットがマーカーとして設定され、次に1〜4ビットが追加のオクレットの数を示すことです。次に、追加の各オクレットで上位2ビットを10に設定する必要があります。
擬似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に変換できます。ただし、不正な形式の文字を取得すると、どのような除去が行われるかは明確ではありません。
c = (ch << 1)
(c & 1)
ループをスキップして、最初はゼロになります。テストはおそらく(c & 128)
質問とは少し異なりますが、私がやっていることはHtmlEncode(string)を使用することです、
ここに擬似コード
var encoded = HtmlEncode(string);
encoded = Regex.Replace(encoded, "&#\d+?;", "");
var result = HtmlDecode(encoded);
入出力
"Headlight\x007E Bracket, { Cafe Racer<> Style, Stainless Steel 中文呢?"
"Headlight~ Bracket, { Cafe Racer<> Style, Stainless Steel 中文呢?"
私はそれが完璧ではないことを知っていますが、私のために仕事をします。
static $preg = <<<'END'
%(
[\x09\x0A\x0D\x20-\x7E]
| [\xC2-\xDF][\x80-\xBF]
| \xE0[\xA0-\xBF][\x80-\xBF]
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
| \xED[\x80-\x9F][\x80-\xBF]
| \xF0[\x90-\xBF][\x80-\xBF]{2}
| [\xF1-\xF3][\x80-\xBF]{3}
| \xF4[\x80-\x8F][\x80-\xBF]{2}
)%xs
END;
if (preg_match_all($preg, $string, $match)) {
$string = implode('', $match[0]);
} else {
$string = '';
}
それは私たちのサービスに働きます
iconvはどうですか:
http://php.net/manual/en/function.iconv.php
PHP自体の中でそれを使用したことはありませんが、コマンドラインでは常にうまく機能しました。無効な文字に置き換えることができます。