2010-07-21 30 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