PHP < 6では、文字列をUnicode文字の配列に分割する最も良い方法は何ですか?入力が必ずしもUTF-8でない場合は?文字列をPHPでUnicode文字の配列に分割する最も良い方法は何ですか?
入力文字列内のUnicode文字セットが別のUnicode文字セットのサブセットであるかどうかを知りたい。
回答の最初のカップルは機能しなかったので、mb_
ファミリーの機能に対してはまっすぐに実行してみませんか?
PHP < 6では、文字列をUnicode文字の配列に分割する最も良い方法は何ですか?入力が必ずしもUTF-8でない場合は?文字列をPHPでUnicode文字の配列に分割する最も良い方法は何ですか?
入力文字列内のUnicode文字セットが別のUnicode文字セットのサブセットであるかどうかを知りたい。
回答の最初のカップルは機能しなかったので、mb_
ファミリーの機能に対してはまっすぐに実行してみませんか?
あなたはPCRE正規表現と 'U' 修飾子を使用することができます。 Pattern Modifiers(引用)を参照してください。
U(PCRE8)
この修飾子は、Perlと互換性 あるPCREの追加 機能をオンにします。パターン 文字列はUTF-8として扱われます。この 修飾子は、UnixではPHP 4.1.0 以上、PHPではwin32ではPHP 4.2.3 から入手できます。 パターンのUTF-8妥当性は、PHP 4.3.5からチェックされています。例えば
、このコードを考慮:
header('Content-type: text/html; charset=UTF-8'); // So the browser doesn't make our lives harder
$str = "abc 文字化け, efg";
$results = array();
preg_match_all('/./', $str, $results);
var_dump($results[0]);
あなたが使用できない結果得られます。
array
0 => string 'a' (length=1)
1 => string 'b' (length=1)
2 => string 'c' (length=1)
3 => string ' ' (length=1)
4 => string '�' (length=1)
5 => string '�' (length=1)
6 => string '�' (length=1)
7 => string '�' (length=1)
8 => string '�' (length=1)
9 => string '�' (length=1)
10 => string '�' (length=1)
11 => string '�' (length=1)
12 => string '�' (length=1)
13 => string '�' (length=1)
14 => string '�' (length=1)
15 => string '�' (length=1)
16 => string ',' (length=1)
17 => string ' ' (length=1)
18 => string 'e' (length=1)
19 => string 'f' (length=1)
20 => string 'g' (length=1)
しかし、このコードで:
header('Content-type: text/html; charset=UTF-8'); // So the browser doesn't make our lives harder
$str = "abc 文字化け, efg";
$results = array();
preg_match_all('/./u', $str, $results);
var_dump($results[0]);
を(正規表現の最後に 'u'があることに注意してください)
は、あなたが望む結果を得る:何らかの理由で正規表現の方法はあなたのために十分でない場合
array
0 => string 'a' (length=1)
1 => string 'b' (length=1)
2 => string 'c' (length=1)
3 => string ' ' (length=1)
4 => string '文' (length=3)
5 => string '字' (length=3)
6 => string '化' (length=3)
7 => string 'け' (length=3)
8 => string ',' (length=1)
9 => string ' ' (length=1)
10 => string 'e' (length=1)
11 => string 'f' (length=1)
12 => string 'g' (length=1)
ホープこれは
+1良い詳細な例! :) –
@ Shadi Almosri:ありがとう:-) –
:-)に役立ちます。私は以前に放棄されたZend_Locale_UTF8
を書きましたが、あなたが自分でそれをやろうとするなら、あなたを助けるかもしれません。
特に、ユニコード文字列を読み込んで扱うクラスZend_Locale_UTF8_PHP5_String
を見て、それらを使って1つの文字(複数のバイトで構成されていることがあります)に分割します。
EDIT:
/**
* Returns the UTF-8 code sequence as an array for any given $string.
*
* @access protected
* @param string|integer $string
* @return array
*/
protected function _decode($string) {
$string = (string) $string;
$length = strlen($string);
$sequence = array();
for ($i=0; $i<$length;) {
$bytes = $this->_characterBytes($string, $i);
$ord = $this->_ord($string, $bytes, $i);
if ($ord !== false)
$sequence[] = $ord;
if ($bytes === false)
$i++;
else
$i += $bytes;
}
return $sequence;
}
/**
* Returns the UTF-8 code of a character.
*
* @see http://en.wikipedia.org/wiki/UTF-8#Description
* @access protected
* @param string $string
* @param integer $bytes
* @param integer $position
* @return integer
*/
protected function _ord(&$string, $bytes = null, $pos=0)
{
if (is_null($bytes))
$bytes = $this->_characterBytes($string);
if (strlen($string) >= $bytes) {
switch ($bytes) {
case 1:
return ord($string[$pos]);
break;
case 2:
return ((ord($string[$pos]) & 0x1f) << 6) +
((ord($string[$pos+1]) & 0x3f));
break;
case 3:
return ((ord($string[$pos]) & 0xf) << 12) +
((ord($string[$pos+1]) & 0x3f) << 6) +
((ord($string[$pos+2]) & 0x3f));
break;
case 4:
return ((ord($string[$pos]) & 0x7) << 18) +
((ord($string[$pos+1]) & 0x3f) << 12) +
((ord($string[$pos+1]) & 0x3f) << 6) +
((ord($string[$pos+2]) & 0x3f));
break;
case 0:
default:
return false;
}
}
return false;
}
/**
* Returns the number of bytes of the $position-th character.
*
* @see http://en.wikipedia.org/wiki/UTF-8#Description
* @access protected
* @param string $string
* @param integer $position
*/
protected function _characterBytes(&$string, $position = 0) {
$char = $string[$position];
$charVal = ord($char);
if (($charVal & 0x80) === 0)
return 1;
elseif (($charVal & 0xe0) === 0xc0)
return 2;
elseif (($charVal & 0xf0) === 0xe0)
return 3;
elseif (($charVal & 0xf8) === 0xf0)
return 4;
/*
elseif (($charVal & 0xfe) === 0xf8)
return 5;
*/
return false;
}
私はUTFへの旅行を含むmb_*
を使用してソリューションを、書くことができました: 私はちょうどので、私は利便性のための重要な方法をコピーしたZFのSVNブラウザがダウンしていることをrelaized -16とバックの文字列のインデックスをスピードアップするために、おそらく愚かな試みで:
$japanese2 = mb_convert_encoding($japanese, "UTF-16", "UTF-8");
$length = mb_strlen($japanese2, "UTF-16");
for($i=0; $i<$length; $i++) {
$char = mb_substr($japanese2, $i, 1, "UTF-16");
$utf8 = mb_convert_encoding($char, "UTF-8", "UTF-16");
print $utf8 . "\n";
}
私はmb_internal_encoding
を避け、より良い運を持っていたし、ちょうどEACにすべてを指定しますh mb_*
コール。私はpreg
ソリューションを使用して巻き上げると確信しています。
preg_match_all
よりやや単純:
preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY)
これは、あなたの文字の1次元配列をバック与えます。マッチオブジェクトの必要はありません。
この回答は、理にかなっています。論理的には、目標は分割することです。すべての文字を一致させることはありません(同じことがバックグラウンド)。私はあなたの解決策について質問に答えるつもりでしたが、少し違いがありました。 "-1"、 "0"、または "NULL"は、 "-1"の代わりに " PHPの標準であるように、「NULL」を使用して[flagsパラメータにスキップ](http://php.net/manual/en/function.preg-split.php)»することができます。 – Armfoot
あなたが望む比較のタイプに応じて、Unicode文字を比較することは自明ではないことに気づいていますか?たとえば、U + 00DCまたはU + 0075 U + 0308と書くことができます。 – derobert
はい、私はそれを認識しています。問題になった場合は、分割前に入力をUnicode標準形式の1つに変換する必要があります。 – joeforker