4

假设我有一个字符串“HET1200 文本字符串”,我需要将其更改为“HET1200 文本字符串”。编码将是 UTF-8。

我怎样才能做到这一点?目前,我使用mb_convert_case($string, MB_CASE_TITLE, "UTF-8");但将“HET1200”更改为“Het1200.

我可以指定一个例外,但它不会是详尽的。所以我宁愿所有大写的单词都保持大写。

谢谢 :)

4

1 回答 1

5

好的,让我们尝试mb_convert_case尽可能接近地重新创建,但只更改每个单词的第一个字符。

实现的相关部分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));
        }
    }
}

基本上,这会执行以下操作:

  • 设置mode0mode将确定我们是否在单词的第一个字符中。如果是0,我们是,否则,我们不是。
  • 遍历字符串的字符。
    • 确定它是什么类型的字符。
      • 如果它是一个单词字符,则设置res为。1更具体地说,1如果它具有属性“标记,非间距”,“标记,封闭”,“其他,格式”,“字母,修饰符”,“符号,修饰符”,“字母,大写”,“字母,小写”,“字母,大写”,“标点符号,其他”或“其他,代理”。奇怪的是,“信,其他”不包括在内。
    • 如果我们不在单词的开头
      • 如果我们在一个单词字符处,将其转换为小写——这是我们不想要的。
      • 否则,我们不在一个单词字符处,我们设置mode0表示我们正在移动到单词的开头。
    • 如果我们在一个单词的开头并且我们确实有一个单词字符
      • 将此字符转换为标题大小写
      • 信号我们不再处于单词的开头。

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 Ítring Uii
于 2010-07-26T17:55:55.377 回答