Как я могу поменять / переключить случай символов в строке, например:
$str = "Hello, My Name is Tom";
После запуска кода я получаю такой результат:
$newstr = "hELLO, mY nAME Is tOM";
Возможно ли это?
Вам нужно будет перебирать строку, проверяя случай каждого символа, вызывая strtolower()
или strtoupper()
в зависимости от ситуации, добавляя измененный символ к новой строке.
Если ваша строка является только ASCII, вы можете использовать XOR:
$str = "Hello, My Name is Tom"; print strtolower($str) ^ strtoupper($str) ^ $str;
Выходы:
hELLO, mY nAME IS tOM
ОК. Я знаю, что у вас уже есть ответ, но какая-то неясная функция strtr () кричит, что будет использоваться для этого;)
$str = "Hello, My Name is Tom"; echo strtr($str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
Очень похоже в функции ответа Марка.
preg_replace_callback( '/[az]/i', function($matches) { return $matches[0] ^ ' '; }, $str )
Я полагаю, что решение может состоять в следующем:
$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;
Который доставит вам:
hELLO, mY nAME IS tOM
т.е. вы:
Проблема в том, что это, вероятно, не будет работать с особым характером, как акценты 🙁
И вот быстрое предложение, которое могло бы (или не могло) работать для некоторых других персонажей:
$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;
Идея, теперь, будет заключаться в использовании mb_strtolower
и mb_strtoupper
: это может помочь со специальными символами и многобайтовыми кодировками …
Я знаю, что этот вопрос старый, но вот мои 2 варианта многобайтовой реализации.
Многофункциональная версия: ( здесь функция mb_str_split ):
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); }
Версия одной функции:
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); }
Следующий скрипт поддерживает символы UTF-8, такие как «±» и т. Д.
<?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;
Самый быстрый способ – с битовой маской. Никаких неуклюжих строковых функций или регулярных выражений. PHP – это оболочка для C, поэтому мы можем легко манипулировать битами, если вы знаете свою логическую функцию, такую как OR, NOT, AND, XOR, NAND и т. Д.:
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; }
Вот что это меняет:
$string{$i} = chr($char ^ 32);
Мы берем N-й символ в $string
и выполняем XOR (^), говоря интерпретатору, чтобы взять целочисленное значение $char
и заменить 6-й бит (32) с 1 на 0 или 0 на 1.
Все символы ASCII находятся в 32 от своих копий (из-за этого ASCII был гениальным дизайном. Поскольку 32 имеет мощность 2 (2 ^ 5), легко сдвинуть биты. Чтобы получить значение ASCII для буквы, используйте встроенную в функции PHP ord()
:
ord('a') // 65 ord('A') // 97 // 97 - 65 = 32
Итак, вы перебираете строку, используя strlen()
в качестве средней части цикла for
, и она будет циклически повторяться столько раз, сколько ваша строка имеет буквы. Если символ в позиции $i
является буквой (az (65-90) или AZ (97-122)), он будет заменять этот символ для прописного или нижнего регистра с использованием битовой маски.
Вот как работает битовая маска:
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)
Мы можем отменить это:
0110 0001 // 97 (A) 0010 0000 // Bitmask of 32 --------- 0100 0001 // 65 (a)
Нет необходимости в str_replace
или preg_replace
, мы просто preg_replace
биты, чтобы добавить или вычесть 32 из значения ASCII символа, и мы заменим случаи. 6-й бит (6-й справа) определяет, имеет ли символ верхний или нижний регистр. Если это 0, это строчные буквы и 1, если в верхнем регистре. Изменение бита от 0 до 1 объявления 32, получение значения в верхнем регистре chr()
и изменение от 1 до 0 вычитает 32, превращая прописную букву в нижнем регистре.
swapCase('userId'); // USERiD swapCase('USERiD'); // userId swapCase('rot13'); // ROT13
Мы можем также иметь функцию, которая меняет случай на конкретный символ:
// $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