2010-02-14 74 views
10

Cómo puedo cambiaré todo/alternar el caso de los caracteres de una cadena, por ejemplo:interruptor de mayúsculas y minúsculas, php

$str = "Hello, My Name is Tom"; 

después de ejecutar el código que conseguir un resultado como este:

$newstr = "hELLO, mY nAME Is tOM"; 

¿Esto es posible?

Respuesta

1

Deberá iterar a través de la cadena probando el caso de cada carácter, llamando al strtolower() o strtoupper() según corresponda, agregando el carácter modificado a una nueva cadena.

+0

¿Alguna idea de cómo comprobar el caso de una cadena? – tarnfeld

+2

Esto probablemente solo funcionará para caracteres ASCII. La alternativa a 'strotolower()' podría ser 'mb_strtolower()'. – Messa

+2

'ctype_lower()' http://php.net/manual/en/function.ctype-lower.php –

0

supongo que una solución podría ser utilizar algo como esto:

$str = "Hello, My Name is Tom"; 
$newStr = ''; 
$length = strlen($str); 
for ($i=0 ; $i<$length ; $i++) { 
    if ($str[$i] >= 'A' && $str[$i] <= 'Z') { 
     $newStr .= strtolower($str[$i]); 
    } else if ($str[$i] >= 'a' && $str[$i] <= 'z') { 
     $newStr .= strtoupper($str[$i]); 
    } else { 
     $newStr .= $str[$i]; 
    } 
} 
echo $newStr; 

Qué le consigue:

hELLO, mY nAME IS tOM 


es decir que:

  • bucle sobre cada personaje de la cadena original
  • si es entre A y Z, que lo puso a minúsculas
  • si es entre A y Z, lo pones a mayúsculas
  • otra cosa, lo mantiene como está

El problema es esto probablemente no va a funcionar muy bien con carácter especial como acentos :-(


Y aquí es una propuesta rápida que podría (o no puede) trabajo para algunos otros personajes:

$str = "Hello, My Name is Tom"; 
$newStr = ''; 
$length = strlen($str); 
for ($i=0 ; $i<$length ; $i++) { 
    if (strtoupper($str[$i]) == $str[$i]) { 
     // Putting to upper case doesn't change the character 
     // => it's already in upper case => must be put to lower case 
     $newStr .= strtolower($str[$i]); 
    } else { 
     // Putting to upper changes the character 
     // => it's in lower case => must be transformed to upper case 
     $newStr .= strtoupper($str[$i]); 
    } 
} 
echo $newStr; 

Una idea, ahora, sería utilizar mb_strtolower y mb_strtoupper: podría ayudar con caracteres especiales y codificaciones multi-byte ...

9

OK Sé que ya tiene una respuesta, pero el strtr un poco oscura() la función está pidiendo a gritos que se utilizará para este;)

$str = "Hello, My Name is Tom"; 
echo strtr($str, 
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 
      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); 
+0

Si quieres tratar con caracteres UTF-8 de múltiples bytes, necesitarás usar strtr ($ str, $ substitutions_array). Este es realmente el medio que uso para quitar acentos de todas las letras de una cuerda UTF8. – user272563

48

Si la cadena es sólo ASCII, puede utilizar XOR:

$str = "Hello, My Name is Tom"; 

print strtolower($str)^strtoupper($str)^$str; 

Salidas:

hELLO, mY nAME IS tOM 
+6

¡eso es hermoso! – Juddling

+1

Juzgando: Gracias :-) – Mike

+2

No entiendo por qué esta no es la respuesta aceptada. – vascowhite

3

Muy similar en función a la respuesta de Mark.

preg_replace_callback(
    '/[a-z]/i', 
    function($matches) { 
     return $matches[0]^' '; 
    }, 
    $str 
) 
+0

¿Cómo funciona esto? ''a '^' '' parece devolver '0' para mí. – Sukima

+0

@Sukima no idea, http://3v4l.org/8fG9E – Leigh

+0

'a'^'' devuelve 'A'. Funciona porque 'A' es 0x41 y 'a' es 0x61 (y lo mismo para todos los A-Z) y porque '' es 0x20. Al xor -ing estás volteando ese bit. En términos simples, está agregando 32 letras mayúsculas haciéndolas minúsculas y restando 32 de letras minúsculas, haciéndolas mayúsculas. – xtempore

0

Sé que esta pregunta es antigua, pero aquí están mis 2 sabores de una implementación de múltiples bytes.

Multi versión de función: (mb_str_split function found here):

function mb_str_split($string) { 
    # Split at all position not after the start:^
    # and not before the end: $ 
    return preg_split('/(?<!^)(?!$)/u', $string); 
} 

function mb_is_upper($char) { 
    return mb_strtolower($char, "UTF-8") != $char; 
} 

function mb_flip_case($string) { 
    $characters = mb_str_split($string); 
    foreach($characters as $key => $character) { 
     if(mb_is_upper($character)) 
      $character = mb_strtolower($character, 'UTF-8'); 
     else 
      $character = mb_strtoupper($character, 'UTF-8'); 

     $characters[$key] = $character; 
    } 
    return implode('',$characters); 
} 

versión de una sola función:

function mb_flip_case($string) { 
    $characters = preg_split('/(?<!^)(?!$)/u', $string); 
    foreach($characters as $key => $character) { 
     if(mb_strtolower($character, "UTF-8") != $character) 
      $character = mb_strtolower($character, 'UTF-8'); 
     else 
      $character = mb_strtoupper($character, 'UTF-8'); 

     $characters[$key] = $character; 
    } 
    return implode('',$characters); 
} 
0

siguiente script soporta caracteres UTF-8 como "a", etc:

<?php 
$str = 'aaAAąAŚĆżź'; 
$newstr = ''; 
preg_match_all('#.#u', $str, $match); 
foreach ($match[0] as $v) 
$newstr.= (($l=mb_strtolower($v, 'UTF-8')) === $v) ? mb_strtoupper($v, 'UTF-8') : $l; 
echo $str, '<br/>', $newstr; 
0

La manera más rápida es con una máscara de bits. No hay funciones de cadenas torpes ni expresiones regulares. PHP es un contenedor de C, por lo que puede manipular los bits con bastante facilidad si sabe que su función lógica como OR, NOT, AND, XOR, NAND, etc ..:

function swapCase($string) { 
    for ($i = 0; $i < strlen($string); $i++) { 
     $char = ord($string{$i}); 
     if (($char > 64 && $char < 91) || ($char > 96 && $char < 123)) { 
      $string{$i} = chr($char^32); 
     } 
    } 
    return $string; 
} 

Esto es lo que cambia:

$string{$i} = chr($char^32); 

tomamos el carácter número N en $string y realizar un XOR (^) dice al intérprete que tomar el valor entero de $char e intercambiando el sexto bit (32) de un 1 a 0 o de 0 a 1.

Todos los caracteres ASCII están a 32 de distancia de sus contrapartes (ASCII era un ingenioso diseño debido a esto. Como 32 tiene una potencia de 2 (2^5), es fácil desplazar bits. Para obtener el valor ASCII de una carta, utilizar el construido en función de PHP ord():

ord('a') // 65 
ord('A') // 97 
// 97 - 65 = 32 

Así se recorre a través de la cadena mediante strlen() como la parte media del bucle for, y se repetirá exactamente el número de veces como su cadena tiene letras. Si el carácter en la posición $i es una letra (a-z (65-90) o A-Z (97-122)), intercambiará ese carácter para la contraparte mayúscula o minúscula utilizando una máscara de bits.

Así es como funciona la máscara de bits:

0100 0001 // 65 (lowercase a) 
0010 0000 // 32 (bitmask of 32) 
--------- // XOR means: we put a 1 if the bits are different, a 0 if they are same. 
0110 0001 // 97 (uppercase A) 

Podemos revertirla:

0110 0001 // 97 (A) 
0010 0000 // Bitmask of 32 
--------- 
0100 0001 // 65 (a) 

No hay necesidad de str_replace o preg_replace, que sólo cambio bits para sumar o restar 32 desde el valor ASCII de el personaje y nosotros intercambiamos casos. El 6º bit (6º desde la derecha) determina si el carácter está en mayúscula o minúscula. Si es un 0, es minúscula y 1 si es mayúscula. Cambiar el bit de un 0 a un anuncio 32, obteniendo el valor en mayúscula chr(), y cambiar de un 1 a un 0 resta 32, convirtiendo una letra mayúscula en minúscula.

swapCase('userId'); // USERiD 
swapCase('USERiD'); // userId 
swapCase('rot13'); // ROT13 

También podemos tener una función que intercambie el caso de un personaje en particular:

// $i = position in string 
function swapCaseAtChar($string, $i) { 
    $char = ord($string{$i}); 
    if (($char > 64 && $char < 91) || ($char > 96 && $char < 123)) { 
     $string{$i} = chr($char^32); 
     return $string; 
    } else { 
     return $string; 
    } 
} 

echo swapCaseAtChar('iiiiiiii', 0); // Iiiiiiii 
echo swapCaseAtChar('userid', 4); // userId 

// Numbers are no issue 
echo swapCaseAtChar('12345qqq', 7); // 12345qqQ 
Cuestiones relacionadas