PHP字符串函数 分类整理与简要源码分析
源码基于PHP5.5.38
addcslashes
add c (style) slashes 为字符串添加C语言风格的反斜线
string addcslashes(string $str, string $charlist)
将$str
字符串中每一个在$charlist
中的字符加上反斜线。
echo addcslashes('abcdefg', 'ad');
//输出\abc\defg
如果$charlist
为空字符串,返回值也是空字符串string '' (length=0)
好玩的现象:
echo addcslashes('\n', '\n');
//输出 \\\n
//这里\n并没有特殊的意思,就是\ 和 n的意思
echo addcslashes("\n", "\n");
//输出 \n
不知道为什么出现这个原因,特意看了下源代码:
/**
这个函数的功能就是将$charlist中的所有字符扫描一篇,确认使用了那些字符。假设$charlist中是aaaaaabbbbbbb,如果不这么做,a,b将会重复使用多次,效率不高。
*/
static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_DC)
{
//input指的是$charlist
unsigned char *end;
unsigned char c;
int result = SUCCESS;
memset(mask, 0, 256); //初始化为0
for (end = input+len; input < end; input++)
{
c=*input;
//这个if 检查input是否是x..y形式,范围表达式
if ((input+3 < end) && input[1] == '.' && input[2] == '.' && input[3] >= c)
{
memset(mask+c, 1, input[3] - c + 1); //将c所代表的字符开始到最右边这段空间的所有位置设为1 mask + c 巧妙的利用指针
input+=3; //这里其实就会跳出for
}
else if ((input+1 < end) && input[0] == '.' && input[1] == '.')
{
//省略一些范围检测
} else {
mask[c]=1; //将c所代表的变量置为1
}
}
return result;
}
PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int should_free, char *what, int wlength TSRMLS_DC)
{
/忽略一些初始化代码
php_charmask((unsigned char *)what, wlength, flags TSRMLS_CC); //在flags中记录$charlist需要用到哪些字符
for (source = (char*)str, end = source + length, target = new_str; source < end; source++)
{
c = *source; //取出$str中的某一个字符
if (flags[(unsigned char)c]) //如果当前字符不在之前记录的函数中,则跳过
{
if ((unsigned char) c < 32 || (unsigned char) c > 126) //32是空格 126是~ 反过来说32-126是ASCII可视字符
{
*target++ = '\\'; //对目前字符首先新增\字符 \\是转义的意思 除此之外的不可见字符 显示为0开头且宽度为3的八进制数
//特殊字符 继续特殊显示不可见的\n字符,被替换成可见的\n字符
switch (c)
{
case '\n': *target++ = 'n'; break;
case '\t': *target++ = 't'; break;
case '\r': *target++ = 'r'; break;
case '\a': *target++ = 'a'; break;
case '\v': *target++ = 'v'; break;
case '\b': *target++ = 'b'; break;
case '\f': *target++ = 'f'; break;
default: target += sprintf(target, "%03o", (unsigned char) c); //sprintf首先在target指针中追加内容再返回字符串长度,来移动target指针
}
continue; //不执行下面的两句语句 避免重复添加
}
*target++ = '\\'; //是记录中的字符 但是不是可视字符
}
*target++ = c; //普通字符不做任何操作,直接添加
}
}
所以addcslashes
函数使用时,会将一些转义字符可视化,其余不可视化的字符显示为八进制数。从源码可以看出,该函数一般不用于处理非ASCII编码。
//测试
echo addcslashes("
", "\n");
//输出\n\n\n\n\n
echo addcslashes(chr(25), chr(25));
//输出 /031
addslashes
add slashes [slæʃiz]
string addslashes(string $str)
主要为了在可能需要转义的语句中的特殊字符前加入反斜线,例如SQL
语句。这些特殊字符包括'
, "
, \
, NULL
,如下文的源代码所示:
switch (*source)
{
case '\0':
*target++ = '\\';
*target++ = '0';
break;
case '\'':
case '\"':
case '\\':
*target++ = '\\'; //不放置break为的就是使用default中的语句,直接在字符串使用
default:
*target++ = *source;
break;
}
不过进行数据库操作还是建议使用框架中的ORM,框架中的查询生成器、或者PDO、最好不要自己构造完整的SQL
语句,避免SQL注入
。
bin2hex
bin to hex
string bin2hex(string $str)
ASCII转换函数,把ASCII转化为十六进制。并不是进制转换函数,例如:
echo bin2hex("ABCD");
//41424344
源码分析:
static char hexconvtab[] = "0123456789abcdef";
for (i = j = 0; i < oldlen; i++)
{
result[j++] = hexconvtab[old[i] >> 4];
//old[i]里面记录的是某一个ASCII码 右移4位
/*
假设old[i] = 'A' => 01000001B
右移4位就只剩0100B了,也就是4,可以去查看ASCII表,你会发现某一个ASCII的前4位,和它的16进制的数值是一样的,因为ASCII是从0000 0000开始编码的。
*/
result[j++] = hexconvtab[old[i] & 15];
//这里和15 => 00001111进行与运算 可以清零old[i]的高4位
}
result[j] = '\0'; //加上C语言的字符串结束符
chop / rtrim
right trim
string rtrim(string $str [,string $character_mask])
函数用于删除字符串右边(末端)的空白字符(一些转义字符)或者给定的字符。空白字符包括,
\t
, \n
, \r
, \0
,\x0B
。如果不给$character_mask
就默认删除空白符。
示例:
var_dump(rtrim('user '));
//string 'user' (length = 4)
var_dump(rtrim('user11111', '1'));
//string 'user' (length = 4)
var_dump(rtrim('user1111 111 ', ' 1'));
//删除多个字符 string 'user' (length = 4)
源码分析之前, 我觉得$character_mask
应该用了之前处理addcslashes
函数中的$charlist
参数的函数php_charmask
。
PHPAPI char *php_trim(char *c, int len, char *what, int what_len, zval *return_value, int mode TSRMLS_DC)
{
register int i;
int trimmed = 0;
char mask[256];
//这里what指针就是$character_mask 我们可以看见 当不传参数时,what为空指针执行第二句php_charmask 把\n等作为字符串参数主动传入,在mask数组中设置好相应的标记
if (what)
{
php_charmask((unsigned char*)what, what_len, mask TSRMLS_CC);
}
else
{
php_charmask((unsigned char*)" \n\r\t\v\0", 6, mask TSRMLS_CC);
}
//使用mode变量是因为 php_trim这个函数共同用于ltrim, rtrim, trim
//mode == 1表示ltrim
//mode == 2表示rtrim
//mode == 3表示trim
//这里使用与运算 技巧如下当mode等于1(0001B)或者3(0011B)的时候,通过& 1(0001B)得到大于0的值; 当mode等于2(0010B)或者3(0011B)的时候,通过& 2(0010B)得到大于0的值。
//感慨一下,,真厉害,,,从来没想过还能这么搞。。。。膜拜一下。。。ofo
if (mode & 1)
{
for (i = 0; i < len; i++)
{
//找到第一个不在标记字符串中的下标
if (mask[(unsigned char)c[i]])
{
trimmed++;
}
else
{
break;
}
}
len -= trimmed;
c += trimmed; //移动指针即可清除首端字符
}
if (mode & 2)
{
for (i = len - 1; i >= 0; i--)
{
if (mask[(unsigned char)c[i]])
{
len--;
}
else
{
break;
}
}
}
//这里涉及到zend内核的一些知识了,return_value是一个很特殊的参数。等我懂了就来补充这里。
if (return_value) {
RETVAL_STRINGL(c, len, 1); //一个宏用于返回定长字符串
} else {
return estrndup(c, len); //复制长度为len的字符串
}
}
chr
character
string chr(int $ascii)
返回整数$ascii
对应的ASCII码
例如:
echo chr(69);
echo chr(325);
//E E
超过256,将会对256取余,但是这不是PHP取余的,而是C语言的影响,源代码如下:
long c;
char temp[2];
/省略zend获取参数代码
temp[0] = (char)c;
//将一个long类型转化为char时,发生强制类型转化,出现截断现象
/*
325 => 0000 ... 0000 0001 0100 0101B (32bit)
69 => 0000 ... 0000 0000 0100 0101B (32bit)
69截断前后无变化,但是325截断以后恰好就是69 所以PHP代码中两个chr结果一样。
*/
temp[1] = '\0';
chunk_split
string chunk_split ( string $body [, int $chunklen = 76 [, string $end = "\r\n" ]] )
将一个字符串使用某个字符串等分开,使用$chunklen
指定长度,$end
指定结尾需要添加的字符串。默认长度为76,默认的分隔符号是\r\n
,最后一部分的长度可能不到$chunklen
。
例如:
$a = '12312nsdkfugsdfbaekrg23895yu2893hrsdbfaf';
var_dump(chunk_split($a, 12, "EOF\n"));
/*string '12312nsdkfugEOF
sdfbaekrg238EOF
95yu2893hrsdEOF
bfafEOF
' (length=56)
*/
一般用于ASCII等分,如果$body
是UTF8字符串,不是很好分割,首先UTF8是不定长编码,不能完全以3个字节的倍数拆分。例如:
$a = '你好啊';
var_dump(chunk_split($a, 3, ","));
//string '你,好,啊,' (length=12)
$a = '你1好2啊';
var_dump(chunk_split($a, 3, ","));
//由于不定长编码所以后面不能正确显示
//string '你,1�,�2�,��,' (length=15)
所以如果确实需要对汉字进行这种操作,并且混用了数字或者字母,那么最好使用定长编码,例如UTF-16,所以首先进行一下转换
$a = '你1好2啊';
$tmp = mb_convert_encoding($a, 'UTF-16', 'UTF-8');
var_dump(
mb_convert_encoding(
chunk_split($tmp, 2,
mb_convert_encoding(',', 'UTF-16', 'UTF-8')
), 'UTF-8', 'UTF-16'));
//mb_convert_encoding(',', 'UTF-16', 'UTF-8')这里必须把,分隔符也要使用UTF16编码,不然加入字符串以后仍会出现乱码。另外一般情况下UTF16是两个字节,但是有时候也有4个字节的。
源代码分析:
chunks = srclen / chunklen;
restlen = srclen - chunks * chunklen; //计算剩余长度
//p和q分别是指向原串和目的串的指针 chunklen即为分割大小 p必须小于原串减去分割块大小 不然会出现拷贝了一些不属于自己的内存单元,比如原串大小为10 块大小为4 第一次拷贝0-3 第二次4-7 第三次8-11(这个不应该出现,所以p不能超过这里的7)
for (p = src, q = dest; p < (src + srclen - chunklen + 1); )
{
memcpy(q, p, chunklen);
q += chunklen; //移动目的串指针,准备追加结尾字符串
memcpy(q, end, endlen);
q += endlen; //移动目的串指针,准备复制下一个小块
p += chunklen; //移动原串指针,准备使用下一个小块
}
//如果还有剩余的长度 再拷贝一次
if (restlen)
{
memcpy(q, p, restlen);
q += restlen;
memcpy(q, end, endlen);
q += endlen;
}
convert_uudecode
string convert_uudecode ( string $data )
解码一个uuencode编码字符串,可以搜索一下uuencode
,是一种字符转换方式,类似于base64
convert_uuencode
string convert_uuencode ( string $data )
使用uuencode
编码字符串,函数与convert_uudecode
是互逆函数。
count_chars
mixed count_chars ( string $string [, int $mode = 0 ] )
统计字符串中所使用的字符信息,通过mode
调整返回值,默认是0
- 0 返回数组,使用字节值作为key,包括所有的字节的使用情况(无论是否出现过)
- 1 同0,但是返回大于零(使用过)的字节值的次数
- 2 同1,但是返回等于零(从未使用过)的字节值出现次数
- 3 返回字符串,包含使用过的字符,按照ASCII排序
- 4 返回字符串,包含没使用过的字符,按照ASCII排序
通过mode
可以看出,模式0的数组 = 模式1的数组 + 模式2的数组;模式3的字符串 + 模式4的字符串等于全部256个字符。
例如:
$test = 'abcdefgh1211111';
var_dump(count_chars($test, 0));
var_dump(count_chars($test, 1));
var_dump(count_chars($test, 2));
var_dump(count_chars($test, 3));
var_dump(count_chars($test, 4));
/*
array (size=256)
...
84 => int 0
85 => int 0
86 => int 0
87 => int 0
88 => int 0
89 => int 0
...
93 => int 0
94 => int 0
95 => int 0
96 => int 0
97 => int 1
98 => int 1
99 => int 1
100 => int 1
101 => int 1
102 => int 1
103 => int 1
104 => int 1
...
array (size=10)
49 => int 6
50 => int 1
97 => int 1
98 => int 1
99 => int 1
100 => int 1
101 => int 1
102 => int 1
103 => int 1
104 => int 1
array (size=246)
0 => int 0
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
more elements...
string '12abcdefgh' (length=10)
string '�
!"#$%&'()*+,-./03456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ijklmnopqrstuvwxyz{|}~€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬�' (length=246)
*/
源码猜测,既然每个模式之前存在一个的加法关系,所以我觉得应该是扫描一遍字符串,统计出使用情况,然后根据mode
值,调整返回值。
//扫描统计
while (len > 0)
{
chars[*buf]++;
buf++;
len--;
}
if (mymode < 3)
{
array_init(return_value); //zend宏初始化数组
}
for (inx = 0; inx < 256; inx++)
{
switch (mymode) {
case 0: //统计所有的出现次数
add_index_long(return_value, inx, chars[inx]);//zend宏在return_val所指向的数组中加入inx => chars[inx]
break;
case 1:
if (chars[inx] != 0) //只加入不为0的
{
add_index_long(return_value, inx, chars[inx]);
}
break;
case 2:
if (chars[inx] == 0) //只加入为0的
{
add_index_long(return_value, inx, chars[inx]);
}
break;
case 3:
if (chars[inx] != 0) //出现过 放入字符串中 由于inx从0开始自增,所以自然而然的就是排序的 下同
{
retstr[retlen++] = inx;
}
break;
case 4:
if (chars[inx] == 0)
{
retstr[retlen++] = inx;
}
break;
}
}
ofo 该函数暂未考虑多字节,如果确实有需要,可能要使用自己实现的函数,试试md_XXX开头的函数。
crc32
int crc32 ( string $str )
生成CRC校验,第一次知道CRC概念的时候,还是在学习计算机网络的时候。
文档上说,由于PHP的int是带符号的,所以生成的CRC在大部分32位系统上呈现负数,你可能需要使用
printf
之类的函数,并且使用%u
。
与这个函数类似的还有md5()
sha1()
hash()
crypt
explode
array explode ( string $delimiter , string $string [, int $limit ] )
使用一个字符串将另一个字符串分割成数组,这个函数需要先指定分割字符,然后是被分割的字符,最后是一个可选的限制参数
- 0 返回仅有一个元素的数组
- >0 返回最多limit
个元素
- <0 返回的数组中,不包括最后的-limit
个元素
$number = '123,123,2,321,434,543,3';
var_dump(explode(',', $number));
var_dump(explode(',', $number, 0));
var_dump(explode(',', $number, 5));
var_dump(explode(',', $number, -5));
/*
array (size=7)
0 => string '123' (length=3)
1 => string '123' (length=3)
2 => string '2' (length=1)
3 => string '321' (length=3)
4 => string '434' (length=3)
5 => string '543' (length=3)
6 => string '3' (length=1)
array (size=1)
0 => string '123,123,2,321,434,543,3' (length=23)
array (size=5)
0 => string '123' (length=3)
1 => string '123' (length=3)
2 => string '2' (length=1)
3 => string '321' (length=3)
4 => string '434,543,3' (length=9)
array (size=2)
0 => string '123' (length=3)
1 => string '123' (length=3)
*/
可以发现,当limit
没有写的时候,会完全分割开;
为0时,相当于返回原串,为1,效果应该和0相同
为其他正数时,分割出的数组至少保证前limit-1
个元素是分割开的,剩余的全部合在一起
为负数时,就是去掉末尾的-limit
个元素,只保留前几个元素
fprintf
int fprintf ( resource $handle , string $format [, mixed $args [, mixed $... ]] )
将使用$format
格式化后的字符串写入流,该函数使用方法的C语言的类似。
$handle
一般使用fopen
函数打开后返回的资源变量,$format
和C语言一致,%d %c %s
什么的。
get_html_translation_table
hex2bin
string hex2bin ( string $data )
和bin2hex
互补,将十六进制的字符串转为ASCII字符串。
$a = 'abcd';
echo bin2hex($a);
echo hex2bin(bin2hex($a));
源码上,应该需要进行a
或者A
的判断,然后把原来的右移,改为左移。
一起看看:
for (i = j = 0; i < target_length; i++) {
char c = old[j++]; //取出16进制编码的字符串的某一个字符 代表高4bit
if (c >= '0' && c <= '9') {
str[i] = (c - '0') << 4;
} else if (c >= 'a' && c <= 'f') {
str[i] = (c - 'a' + 10) << 4;
} else if (c >= 'A' && c <= 'F') {
str[i] = (c - 'A' + 10) << 4;
} else {
efree(str);
return NULL;
}
c = old[j++]; //低4bit
if (c >= '0' && c <= '9') {
str[i] |= c - '0'; //进行与运算 低4位之前全是0 现在与上新的低4bit,组成一个完整的8bit字符
} else if (c >= 'a' && c <= 'f') {
str[i] |= c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
str[i] |= c - 'A' + 10;
} else {
efree(str);
return NULL;
}
}
html_entity_decode
string html_entity_decode ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") ]] )
与htmllentities
函数互逆
htmlentities
string htmlentities ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = true ]]] )
几乎和htmlspecialchars
,除了该函数会转换所有具有HTML实体的字符。如果字符串中有中文最好使用htmlspecialchars
函数,否则可能会出现乱码。
htmlspecialchars_decode
string htmlspecialchars_decode ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 ] )
与htmlspecialchars
互逆。
htmlspecialchars
string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = true ]]] )
将特殊字符转换为HTML实体。
通过设置$flags
可以设置一下处理细节,比如不转换单引号,也可以设置文档类型
通过$encoding
设置字符串的编码,默认使用当前的字符。
如果关闭了double_encode
,就不会转换现有的HTML实体。
该函数能转换的字符有限只有:
字符 | 替换后的结果 |
---|---|
& | & |
‘ | " |
“ | ' /' |
> | < |
< | > |
implode / join
string implode ( string $glue , array $pieces )
string implode ( array $pieces )
使用(或者不用)$glue
将数组合并成一个字符串,各元素之前使用$glue
隔开,和explode
互补。
$arr = ['1', '2', '3'];
var_dump(implode($arr));
var_dump(implode(',', $arr));
/*
string '123' (length=3)
string '1,2,3' (length=5)
*/
这个数组的元素可以使用整型,浮点型,字符串, 对象或者混用。对象必须自己实现__toString()
方法.
lcfirst
string lcfirst ( string $str )
使一个字符串的第一个字符小写(大写请参考ucfirst
)
$a = 'Acd Rty';
echo lcfirst($a);
//acd Rty
源代码:
r = str;
*r = tolower((unsigned char) *r);
levenshtein
int levenshtein ( string $str1, string $str2)
计算两个字符之间的编辑距离,即通过替换,插入,删除等操作把$str1
替换成$str2
的最短距离。
最短距离,可以近似的描述两个单词之间的相似性。
localeconv
ltrim
string ltrim ( string $str [, string $character_mask ] )
删除字符串开头(左边)的某些字符,与rtrim
类似
md5_file
string md5_file ( string $filename [, bool $raw_output = false ] )
计算文件的MD5散列值,相似的函数还有sha1_file
md5
string md5 ( string $str [, bool $raw_output = false ] )
计算字符串的MD5散列值
metaphone
money_format
nl_langinfo
nl2br
string nl2br ( string $string [, bool $is_xhtml = true ] )
new line to br
在字符串中的新行中插入<br/>
或者<br>
,类似于做字符串替换。
number_format
ord
int ord ( string $string)
返回字符的ASCII编码,与chr是互逆函数。
parse_str
int print( string $arg)
与echo相似,但是print仅能使用一个参数,这是语言结构,可以不用( )
;
printf
类似于C语言的printf
quoted_printable_decode
quoted_printable_encode
quotemeta
rtrim
string rtrim ( string $str [, string $character_mask ] )
删除字符串右边的空白字符(或者自定义字符)
细节描述,请参考ltrim
setlocale
similar_text
soundex
sprintf
sscanf
str_getcsv
str_ireplace
str_pad
string str_pad ( string $input , int $pad_length [, string $pad_string = " " [, int $pad_type = STR_PAD_RIGHT ]] )
字符串充填,将字符串使用另一个字符串(在左边,右边,或者同时)充填至指定长度。
var_dump(str_pad('123', 6, 'A', STR_PAD_LEFT));
var_dump(str_pad('123', 6, 'ABCD', STR_PAD_LEFT));
var_dump(str_pad('123', 6, 'A', STR_PAD_BOTH));
var_dump(str_pad('123', 6, 'AB', STR_PAD_BOTH));
/*
string 'AAA123' (length=6)
string 'ABC123' (length=6)
string 'A123AA' (length=6)
string 'A123AB' (length=6)
*/
从输出结果可以看到,如果不能完全被充填,用来充填的字符串会被缩短,
另外如果使用STR_PAD_BOTH
方式,左右两边如果不能均分,右边会多一点。
来看看源代码究竟是怎么回事儿吧:
switch (pad_type_val) {
case STR_PAD_RIGHT:
left_pad = 0;
right_pad = num_pad_chars;
break;
case STR_PAD_LEFT:
left_pad = num_pad_chars;
right_pad = 0;
break;
case STR_PAD_BOTH:
left_pad = num_pad_chars / 2;
//左边充填长度等于充填长度的一半
right_pad = num_pad_chars - left_pad;
//右边充填长度等于充填长度减去左边的长度 由于计算机除法的特殊性,导致左边充填长度 小于右边的,且刚好差一
break;
}
for (i = 0; i < left_pad; i++)
result[result_len++] = pad_str_val[i % pad_str_len]; //在结果字符串中放入左边需要充填的字符,通过%循环放置
memcpy(result + result_len, input, input_len); //复制原始字符串
result_len += input_len; //更新长度
for (i = 0; i < right_pad; i++)
result[result_len++] = pad_str_val[i % pad_str_len];//充填右边
在我们看了源代码之后,之前的疑问就解决了。
str_repeat
string str_repeat ( string $input , int $multiplier )
将一个字符串重复$multiplier
次,并且返回结果。这个函数有点像:
function repeat($str, $k)
{
$res = '';
for ($i = 0; $i < $k; $i++) {
$res .= $str;
}
return $res;
}
调用一下试试:
echo str_repeat('123', 0); //返回空串
echo str_repeat('123', 3); //正常
echo str_repeat('123', -3); //报错
源码猜测,应该是提前分配空间 然后复制,或者直接使用memcpy:
result = (char *)safe_emalloc(input_len, mult, 1); //利用zend宏分配大小 分配的大小等于input_len * mult + 1 满足复制要求
if (input_len == 1) {
memset(result, *(input_str), mult); //特别的 如果输入的字符串只有一个字符,直接把这片内存区域设置为这个字符
} else {
char *s, *e, *ee;
int l=0;
memcpy(result, input_str, input_len);
s = result;
e = result + input_len;
ee = result + result_len;
while (e<ee) {
l = (e-s) < (ee-e) ? (e-s) : (ee-e);
memmove(e, s, l);
e += l;
}
}
str_replace
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
把$subject
中,含有$search
的部分替换为$replace
,如果设置了$count
,将会返回发生替换的次数。
$count = 0;
var_dump(str_replace('a', 'b', 'aaaaa', $count));
echo $count;
//bbbbb 5
str_replace
不仅仅可以用于字符串,也可以用于数组。
var_dump(str_replace('a', 'b', ['a', 'b', 'aa']));
/*
array (size=3)
0 => string 'b' (length=1)
1 => string 'b' (length=1)
2 => string 'bb' (length=2)
*/
var_dump(str_replace(1, 2, [1, 12, 111]));
/*
array (size=3)
0 => string 'b' (length=1)
1 => string 'b' (length=1)
2 => string 'bb' (length=2)
*/
数组里面的元素,会被当做字符串。
这个函数源码使用了太多了的宏,看不懂。。。。QAQ
str_rot13
string str_rot13 (string $str)
对字符串执行ROT13转换
echo str_rot13('abcdxyzm123');
//nopqklmz123
$arr = '';
for($i = 33; $i <= 126; $i++){
$arr .= chr($i);
}
var_dump($arr);
var_dump(str_rot13($arr));
/*
string '!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~' (length=94)
string '!"#$%&'()*+,-./0123456789:;<=>?@NOPQRSTUVWXYZABCDEFGHIJKLM[\]^_`nopqrstuvwxyzabcdefghijklm{|}~' (length=94)
对比可以看出这个函数,仅仅会影响A-Za-z的字符。
*/
应该是可以通过简单的取余就可以实现,另外不知道这个函数有啥用?
str_shuffle
string str_shuffle ( string $str )
随机打乱一个字符串。
源代码
n_elems = len;
if (n_elems <= 1) {
return;
}//长度不足1 无需打乱
n_left = n_elems;
while (--n_left) { //循环len次
rnd_idx = php_rand(TSRMLS_C);
RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
//利用宏产生随机数,猜测范围应该在0-n_left之间
if (rnd_idx != n_left) {
temp = str[n_left];
str[n_left] = str[rnd_idx];
str[rnd_idx] = temp;
} //交换
}
str_split
array str_split ( string $string [, int $split_length = 1 ] )
将字符串转化为数组,数组中每个元素的字节不超过$split_length
。
var_dump(str_split('12345', 3));
/*
array (size=2)
0 => string '123' (length=3)
1 => string '45' (length=2)
*/
不用于explode
使用分割字符将字符串分割为数组,str_split
只能按照固定大小分割,分割出来的数组,除了最后一个元素大小不一样,其余元素字节数应该是固定的
如果要对多字节字符串按照字符分割(不是字节),建议转化为定长编码,然后按照一定的倍数,改写函数。
str_word_count
strcasecmp
int strcasecmp ( string $str1, string $str2)
二进制安全比较字符串,不区分大小写。区别于strcmp
二进制安全:所谓二进制安全指的是在一个二进制文件上所执行的不更改文件内容的功能和操作,本质上是讲操作输入作为元素的、无任何特殊格式意义的数据流。比如用PHP的string存储图形或者音频的二进制数据流,那么里面一些比如\0的字节,不应该作为字符串结束标志。
var_dump(strlen("123 \0 123\0"));
//int 10
echo strcasecmp('ab', 'Ab'); //0
echo strcasecmp('ab', 'A'); //1
strchr
strstr
的别名
别名的出现 一方面是两个名称都非常合适,另一方面是为了确保向后兼容性。
strcmp
int strcmp ( string $str1, string $str2)
和strcasecmp
唯一的不同就是不是区分大小写的。在这个函数里面小写字母比大写字母大,所以推测函数使用ASCII直接进行比较。
echo strcmp('Ab', 'a'); //-1
strcoll
int strcoll ( string $str1 , string $str2 )
基于区域设置的字符串比较,非二进制安全。
区域设置通过setlocale
修改
strcspn
strip_tags
string strip_tags ( string $str [, string $allowable_tags ] )
去除字符串中的HTML标签,如果设置了$allowable_tags
那么这里面的标签不会去掉。
var_dump(strip_tags('<p><span>123</span>456</p>');
//string '123456' (length = 6)
var_dump(strip_tags('<123>456</123>'));
//string '456' (length=3)
这个函数并不是完全针对HTML标签,实际上只要包含在<>
的都会去掉。
stripcslashes
string stripcslashes ( string $str )
这个函数与addcslashes
是一个相反的函数,也就是把之前添加了C语言风格的\n
,\r
什么的去掉。
var_dump(stripcslashes('\n\n\n'));
/*
string '
' (length=3)
*/
stripos
mixed stripos ( string $haystack , string $needle [, int $offset = 0 ] )
字符串查找函数,查找$haystack
中$needle
首次出现的位置,这个函数不区分大小写。
找不到时会返回false
,字符串从0
开始编号
var_dump(stripos('ABCDEFG', 'DE')); //3
var_dump(stripos('ABCDEFG', 'de')); //3
var_dump(stripos('ABCDEFG', 'K')); //false
stripslashes
string stripslashes ( string $str )
这个函数与stripcslashes
类似,都拥有一个相反的函数,该函数的相反函数就是addslashes
.
$str = addslashes("\\\\");
var_dump($str);
var_dump(stripslashes($str));
/*
string '\\\\' (length=4)
string '\\' (length=2)
*/
stristr
string stristr ( string $haystack , mixed $needle [, bool $before_needle = false ] )
默认返回在$haystack
中第一次出现$needle
到字符串尾的所有字符串。如果设置了$before_needle
为true,那么会返回,从字符串头到第一次出现$needle
处的所有字符串(不包括$needle
)。如果找不到这样的元素会返回false
。这个函数是strstr的 不区分大小写版本,猜测函数中的i
表示ignore
的意思。
echo stristr('1234567', '4'); //4567
echo stristr('1234567', '8'); //false
echo stristr('1234567', '4', true); //
strlen
int strlen ( string $string )
获取字符串的长度,类似于C语言函数,但是不完全相同,并不会把字符\0
作为字符串的结束符。
echo strlen("123 \0 456");
//输出9 6个可见字符,2个空格,1个\0 而不是输出4
这是一个以单字节ASCII为基础的函数,如果需要测量多字节字符串,参考md_strlen()
。
strnatcasecmp
strnatcmp
strncasecmp
strncmp
strpbrk
strpos
mixed strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
在$haystack
中查找$needle
首次出现的位置,如果设置了$offset
,就会从当前开始查找,找不到输出false
echo strpos('12345678', '123'); //0
echo strpos('12345678', '123', 2); //false
如果为负值,文档上说会从距离尾部
-$offset
处,开始查找。但是实际在5.8版本测试时,报错!
strrchr
string strrchr ( string $haystack , mixed $needle )
查找指定字符在$haystack
中最后出现的位置及其之后的所有字符串。$needle
可以使用字符串,但是仅使用第一个字符。如果使用了数字,将会转换为其所对应的ASCII字符。
echo strrchr('12345613456', '123'); //13456
echo strrchr('1234561A3456', 65); //A3456
strrev
string strrev ( string $string )
反转字符串,相当于把一个字符倒序遍历。
echo strrev('1234') // 4321
strripos
int strripos ( string $haystack , string $needle [, int $offset = 0 ] )
查找指定字符串首次出现的位置,通过offset
设置字符串的起始位置。
echo strripos('1234523', '23'); //5
echo strripos('1234523', '23', 4); //5
echo strripos('1234523', '23', -4); //1
如果offset
为正数,那么查找的范围为offset到字符串尾部,如果为负数,那么查找范围为0~offset处。找不到时会返回false,该函数是不区分大小写的。
strrpos
int strripos ( string $haystack , string $needle [, int $offset = 0 ] )
函数strripos
的不区分大小写版本。
strspn
strstr
stristr
函数的不区分大小写版本,用法相同,二进制安全函数。
strtok
strtolower
string strtolower ( string $string )
将字符串中的字母全部转换为小写,字母与区域有关。
echo strtolower('AbCd'); //abcd
strtoupper
string strtoupper( string $string)
将字符串中的字母全部转换为大写,与strtolower
不完全可逆。
strtr
substr_compare
substr_count
substr_replace
substr
trim
string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )
函数ltrim
和rtirm
结合使用的效果,同时去除字符串两侧的空白字符(或者指定字符)。
ucfirst
string ucfirst ( string $str )
和lcfirst
相似,把字符串的第一个字母大写,同样对于字母而言,转换依赖区域设置。
ucwords
string ucwords ( string $str [, string $delimiters = " \t\r\n\f\v" ] )
将字符串中的每个单词的首字母大写,单词之间,用$delimiters
分割。
echo ucwords('my name is li lei');
//My Name Is Li Lei
vfprintf
int vfprintf ( resource $handle , string $format , array $args )
将vprintf
函数的结果输出到$handle
的方法。
vprintf
int vprintf ( string $format , array $args )
与printf
类似,但是vprintf
接受一个数组参数,而不是可变参数。
vprintf("%d %d %d", [1,2,3,4]);
//输出1 2 3 参数可以多,但是绝对不能少
返回的int
表示字符串的长度。
vsprintf
string vsprintf ( string $format , array $args )
与vprintf
相似,不输出字符,而是返回字符串