4

文字列「HET1200テキスト文字列」があり、「HET1200テキスト文字列」に変更する必要があるとします。エンコーディングはUTF-8になります。

どうやってやるの?現在使用していますmb_convert_case($string, MB_CASE_TITLE, "UTF-8");が、「HET1200」が「Het1200」に変わります。

例外を指定することもできますが、それだけでは不十分です。だから私はむしろすべて大文字のままで大文字のままにします。

ありがとう :)

4

1 に答える 1

5

mb_convert_caseOK、できるだけ近くで再作成してみましょう。ただし、すべての単語の最初の文字のみを変更します。

mb_convert_case実装の関連部分は次のとおりです。

int mode = 0; 

for (i = 0; i < unicode_len; i+=4) {
    int res = php_unicode_is_prop(
        BE_ARY_TO_UINT32(&unicode_ptr[i]),
        UC_MN|UC_ME|UC_CF|UC_LM|UC_SK|UC_LU|UC_LL|UC_LT|UC_PO|UC_OS, 0);
    if (mode) {
        if (res) {
            UINT32_TO_BE_ARY(&unicode_ptr[i],
                php_unicode_tolower(BE_ARY_TO_UINT32(&unicode_ptr[i]),
                    _src_encoding TSRMLS_CC));
        } else {
            mode = 0;
        }   
    } else {
        if (res) {
            mode = 1;
            UINT32_TO_BE_ARY(&unicode_ptr[i],
                php_unicode_totitle(BE_ARY_TO_UINT32(&unicode_ptr[i]),
                    _src_encoding TSRMLS_CC));
        }
    }
}

基本的に、これは次のことを行います。

  • に設定mode0ます。mode単語の最初の文字にいるかどうかを判断します。もしそうなら0、そうでなければ、そうではありません。
  • 文字列の文字を繰り返し処理します。
    • それがどんな種類のキャラクターであるかを決定します。
      • 単語文字の場合はに設定resします。1具体的に1は、プロパティが「Mark、Non-Spacing」、「Mark、Enclosing」、「Other、Format」、「Letter、Modifier」、「Symbol、Modifier」、「Letter、Uppercase」、「文字、小文字」、「文字、タイトルケース」、「句読点、その他」または「その他、代理」。奇妙なことに、「手紙、その他」は含まれていません。
    • 単語の先頭にいない場合
      • 単語の文字を使用している場合は、小文字に変換します。これは望ましくないことです
      • それ以外の場合は、単語の文字ではなく、単語の先頭に移動していることを通知するように設定modeします。0
    • 私たちが単語の始まりにいて、実際に単語の文字を持っている場合
      • この文字をタイトルケースに変換する
      • 単語の先頭ではなくなったことを知らせます。

mbstring拡張子は、文字のプロパティを公開していないようです。mb_convert_caseこれは問題を残します。なぜなら、キャラクターがテスト対象の10個のプロパティのいずれかを持っているかどうかを判断する良い方法がないからです。

幸い、正規表現のUnicode文字プロパティはここで私たちを救うことができます。

mb_convert_case問題のある小文字への変換なしでの忠実な複製は次のようになります。

function mb_convert_case_utf8_variation($s) {
    $arr = preg_split("//u", $s, -1, PREG_SPLIT_NO_EMPTY);
    $result = "";
    $mode = false;
    foreach ($arr as $char) {
        $res = preg_match(
            '/\\p{Mn}|\\p{Me}|\\p{Cf}|\\p{Lm}|\\p{Sk}|\\p{Lu}|\\p{Ll}|'.
            '\\p{Lt}|\\p{Sk}|\\p{Cs}/u', $char) == 1;
        if ($mode) {
            if (!$res)
                $mode = false;
        }
        elseif ($res) {
            $mode = true;
            $char = mb_convert_case($char, MB_CASE_TITLE, "UTF-8");
        }
        $result .= $char;
    }

    return $result;
}

テスト:

echo mb_convert_case_utf8_variation("HETÁ1200 Ááxt ítring uii");

与える:

HETÁ1200ÁáxtÍtringUii
于 2010-07-26T17:55:55.377 に答える