2010-07-21 7 views
3

En supposant que j'ai une chaîne "chaîne de texte HET1200" et que j'en ai besoin pour la remplacer par "chaîne de texte HET1200". L'encodage serait UTF-8.php mb_convert_case() Conserve les mots en majuscules

Comment puis-je faire cela? À l'heure actuelle, j'utilise mb_convert_case($string, MB_CASE_TITLE, "UTF-8"); mais que les modifications « HET1200 » à « Het1200

je pourrais spécifier une exception, mais ce ne sera pas une liste exhaustive Je plutôt tous les mots en majuscules pour rester en majuscules

Merci...:)

Répondre

4

OK, nous allons essayer de recréer mb_convert_case le plus près possible mais seulement changer le premier caractère de chaque mot

la partie pertinente de mb_convert_case mise en œuvre est la suivante:.

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)); 
     } 
    } 
} 

En fait, cela fait comme suit:

  • Set mode-0. mode déterminera si nous sommes dans le premier caractère d'un mot. Si c'est 0, nous sommes, sinon, nous ne le sommes pas.
  • Effectue une itération sur les caractères de la chaîne.
    • Déterminez le type de caractère.
      • Définissez res à 1 s'il s'agit d'un caractère de mot. Plus précisément, définissez-le sur 1 s'il a la propriété "Marquer, Pas d'espacement", "Marque, Enveloppe", "Autre, Format", "Lettre, Modificateur", "Symbole, Modificateur", "Lettre, Majuscules", "Lettre, Minuscule", "Lettre, Titlecase", "Ponctuation, Autre" ou "Autre, Surrogate". Curieusement, "Lettre, Autre" n'est pas inclus.
    • Si nous ne sommes pas au début d'un mot
      • Si nous sommes à un caractère de mot, le convertir en minuscules - ce que nous ne voulons pas.
      • Sinon, nous ne sommes pas à un caractère de mot, et nous avons mis mode à 0 pour signaler que nous passons au début d'un mot.
    • Si nous sommes au beggining d'un mot et nous avons en effet un caractère de mot
      • Convertir ce personnage à titre
      • cas
      • Signal nous ne sommes plus au début d'un mot.

L'extension mbstring ne semble pas exposer les propriétés de caractère. Cela nous laisse un problème, car nous n'avons pas un bon moyen de déterminer si un caractère possède l'une des 10 propriétés pour lesquelles mb_convert_case teste.

Heureusement, unicode character properties in regex peut nous sauver ici.

Une reproduction fidèle de mb_convert_case avec la conversion en minuscules problématique devient:

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; 
} 

Test:

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

donne:

 
HETÁ1200 Ááxt Ítring Uii 
+0

merci. c'est ingénieux! vraiment apprécier votre explication aussi. :) – Lyon

Questions connexes