13

str_word_count()UTF-8 文字列で使用したい。

これはPHPで安全ですか?そうあるべきだと私には思えます(特に がないことを考えるとmb_str_word_count())。

しかし、php.net では、関数の独自の「マルチバイト互換」バージョンを提示することで、混乱を招いている人がたくさんいます。

だから知りたいんだろうな…

  1. str_word_count(スペース)で区切られたすべての文字シーケンスを単純にカウントすることを考えると" "、文字シーケンスを必ずしも認識していなくても、マルチバイト文字列で安全であるはずですよね?

  2. ASCII (スペース) ではない、UTF-8 に相当する「スペース」文字はあり" "ますか?#

ここに問題があると思います。

4

4 に答える 4

4

私はあなたが正しいと思います。実際、UTF-8 には US-ASCII の一部ではないスペース文字があります。そのようなスペースの例を挙げると:

そしておそらく同様に:

とにかく、最初のもの - 'NO-BREAK SPACE' (U+00A0) - は、Latin-X 文字セットの一部でもあるため、良い例です。また、PHP のマニュアルには、ロケールに依存するヒントが既にstr_word_count 記載されています。

これをテストしたい場合は、ロケールを UTF-8 に設定し、\xA0シーケンスを含む無効な文字列を渡します。これでも単語分割文字としてカウントされる場合、その関数は明らかに UTF-8 セーフではありません。したがって、マルチバイトセーフではありません(質問と同じように未定義):

<?php
/**
 * is PHP str_word_count() multibyte safe?
 * @link https://stackoverflow.com/q/8290537/367456
 */

echo 'New Locale: ', setlocale(LC_ALL, 'en_US.utf8'), "\n\n";

$test   = "aword\xA0bword aword";
$result = str_word_count($test, 2);

var_dump($result);

出力:

New Locale: en_US.utf8

array(3) {
  [0]=>
  string(5) "aword"
  [6]=>
  string(5) "bword"
  [12]=>
  string(5) "aword"
}

このデモが示すように、その関数はマニュアル ページで提供されているロケールの約束で完全に失敗します (関数が PHP でロケール固有であることを読んだ場合、ほとんどの場合、関数を実行して見つけます。これは、UTF-8 文字エンコーディングに関して何もしないことを示すためにここで利用します。

UTF-8 の代わりに、PCRE 拡張を調べる必要があります。

PCRE は、特に PHP の Unicode と UTF-8 をよく理解しています。正規表現パターンを慎重に作成すると、非常に高速になることもあります。

于 2013-10-10T07:23:06.750 に答える
1

「テンプレートの回答」について-「より速く作業する」という要求はありません。ここでは長い時間や多くのカウントについて話しているわけではないので、数ミリ秒長くかかるかどうかは誰が気にしますか?

ただし、ソフト ハイフンを使用する str_word_count は次のようになります。

function my_word_count($str) {
  return str_word_count(str_replace("\xC2\xAD",'', $str));
}

アサーションに準拠する関数 (ただし、おそらく str_word_count よりも高速ではありません):

function my_word_count($str) {
  $mystr = str_replace("\xC2\xAD",'', $str);        // soft hyphen encoded in UTF-8
  return preg_match_all('~[\p{L}\'\-]+~u', $mystr); // regex expecting UTF-8
}

preg 関数は、a) 既にカウントを返すため、一致を提供する必要がないことを除いて、既に提案されているものと本質的に同じです。


コメントについて:

あなたの PCRE 関数は私の preg_word_count() よりも wrost (パフォーマンス) であることがわかります。必要のない str_replace が必要なためです: '~[^\p{L}\'-\xC2\xAD]+~u' は正常に動作します ( !)。

別のこと、文字列の置換はマルチバイト文字のみを削除すると考えましたが、あなたの正規表現はそれらが表示される可能性のある順序で処理されますが、これは間違っています\\xC2。\xC2\xAE である登録済みの記号\\xADを考えてみましょう。

しかし、有効な UTF-8 の仕組みから考えると、それほど問題にはならないので、同じように使用できるはずです。したがって、関数を持つことができます

function my_word_count($str) {
  return preg_match_all('~[\p{L}\'\-\xC2\xAD]+~u', $str); // regex expecting UTF-8
}

マッチやその他の交換は必要ありません。

str_word_count(str_replace("\xC2\xAD",'', $str));については、UTF8で安定していれば良いのですが、そうではないようです

このスレッドを読むと、有効な UTF-8 文字列を使用する場合に str_replace が安全であることがわかります。あなたのリンクに反対の証拠はありませんでした。

于 2013-10-16T09:07:29.970 に答える
-2

スペース、またはその間の単語の数を数えるだけです。興味があれば、explode と count を使用して独自のカウント関数を作成できます。

ASCII スペース バイトが見つかると、いつでも分割され、そこにすべてが存在します。

于 2011-11-28T01:29:42.327 に答える