2010-07-21 49 views
3

假設我有一個字符串「HET1200文本字符串」,我需要它更改爲「HET1200文本字符串」。編碼將是UTF-8。php mb_convert_case()保留大寫字母

我該怎麼做?目前,我用mb_convert_case($string, MB_CASE_TITLE, "UTF-8");但改變「HET1200」到「Het1200

我可以指定一個例外,但它不會是一個詳盡的所以我寧願所有大寫單詞保持大寫

感謝。: )

回答

4

OK,讓我們嘗試重新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。 「Letter,Lowercase」,「Letter,Titlecase」,「標點符號,其他」或「其他代理人」。奇怪的是,「信,其他」不包括在內。
    • 如果我們在一個字
      • 如果我們在單詞字符的開始不是,將其轉換爲小寫 - 這是我們不希望
      • 否則,我們不是一個單詞字符,並且我們將mode設置爲0以表示我們正在移動到單詞的開頭。
    • 如果我們在單詞的beggining,我們確實有一個單詞字符
      • 轉換這個角色大寫的標題
      • 信號我們不再在一個單詞的開頭。

的mbstring擴展似乎並沒有露出字符屬性。這給我們留下了一個問題,因爲我們沒有一個好的方法來確定一個角色是否具有mb_convert_case測試的10個屬性中的任何一個。

幸運的是,unicode character properties in regex可以拯救我們在這裏。

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 
+0

謝謝。這很巧妙!也非常感謝你的解釋。 :) – Lyon 2010-07-31 13:41:16