如何在字符串中交换/切换字符的大小写,例如:
$str = "Hello, My Name is Tom";
运行代码后,得到如下结果:
$newstr = "hELLO, mY nAME Is tOM";
这甚至可能吗?
答案 0 :(得分:58)
如果您的字符串仅为ASCII,则可以使用XOR:
$str = "Hello, My Name is Tom";
print strtolower($str) ^ strtoupper($str) ^ $str;
输出:
hELLO, mY nAME IS tOM
答案 1 :(得分:9)
好的我知道你已经得到了答案,但是有点模糊的strtr()函数却急于用于此;)
$str = "Hello, My Name is Tom";
echo strtr($str,
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
答案 2 :(得分:4)
功能与Mark的答案非常相似。
preg_replace_callback(
'/[a-z]/i',
function($matches) {
return $matches[0] ^ ' ';
},
$str
)
答案 3 :(得分:2)
最快的方法是使用位掩码。没有笨重的字符串函数或正则表达式。 PHP是C的包装器,所以如果你知道你的逻辑函数如OR,NOT,AND,XOR,NAND等,我们可以很容易地操作位。:
regToken
这就改变了它:
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个字符并执行XOR(^),告诉解释器取整数值$string
并将第6位(32)从1交换为0或0到1。
所有ASCII字符都与它们的对应物相差32个(因为这是一个巧妙的设计。由于32是2(2 ^ 5)的幂,它很容易移位。要获得ASCII值一封信,使用内置的PHP函数$char
:
ord()
所以你使用ord('a') // 65
ord('A') // 97
// 97 - 65 = 32
循环遍历字符串作为strlen()
循环的中间部分,并且它将完全循环,因为你的字符串有字母。如果位置for
处的字符是字母(a-z(65-90)或A-Z(97-122)),它将使用位掩码将该字符替换为大写或小写对应字符。
以下是位掩码的工作原理:
$i
我们可以改变它:
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
,我们只需交换位以从字符的ASCII值中添加或减去32,我们就会交换案例。第6位(右起第6位)确定字符是大写还是小写。如果它是0,那么它是小写的,如果是大写的则是1。将位从0更改为1广告32,获取大写preg_replace
值,并从1更改为0减去32,将大写字母变为小写。
chr()
我们还可以使用一个函数来交换特定字符的大小写:
swapCase('userId'); // USERiD
swapCase('USERiD'); // userId
swapCase('rot13'); // ROT13
答案 4 :(得分:1)
您需要遍历测试每个字符大小写的字符串,根据需要调用strtolower()
或strtoupper()
,将修改后的字符添加到新字符串中。
答案 5 :(得分:0)
我想解决方案可能是使用这样的东西:
$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
:它可能有助于处理特殊字符和多字节编码......
答案 6 :(得分:0)
我知道这个问题已经过时了 - 但这是我的两种多字节实现方式。
多功能版: (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);
}
单一功能版本:
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);
}
答案 7 :(得分:0)
以下脚本支持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;
答案 8 :(得分:0)
切换大小写的最简单方法是:
echo "tOGGLE cASE : ".(strtolower($str) ^ strtoupper($str) ^ $str);
答案 9 :(得分:0)
对于多字节/Unicode 安全的解决方案,我可能会建议根据哪个捕获组包含一个字母来改变/切换每个字母的大小写。这样您就不必在将字母与正则表达式匹配后进行多字节检查。
代码:(Demo)
$string = 'aaAAąAŚĆżź';
echo preg_replace_callback(
'/(\p{Lu})|(\p{Ll})/u',
function($m) {
return $m[1]
? mb_strtolower($m[1])
: mb_strtoupper($m[2]);
},
$string
);
// AAaaĄaśćŻŹ
有关如何匹配可能是多字节的字母的信息,请参阅 this answer。