标题:【PHP小课堂】学习PHP中的字符串操作函数(二)
学习PHP中的字符串操作函数(二)
接下来我们继续 PHP 中字符串函数的学习。今天学习的内容主要是带下划线的一些字符串函数,上篇文章说过,这些系统函数的命名是 PHP 非常令人诟病的,有些东西真的只能靠我们的记忆来强行记住,并没有什么特别的规律可循。
字符串替换
首先还是我们的字符串替换,这个函数应该也是我们字符串操作中使用频率最高的函数之一。
$str = "abcdefGHIjklMnOpQRSTUVWXYZabcdefGHIjklMnOpQRSTUVWXYZ";
$strC = "测试中文数据";
echo str_replace('abc', 'cba', $str, $count), PHP_EOL; // cbadefGHIjklMnOpQRSTUVWXYZcbadefGHIjklMnOpQRSTUVWXYZ
echo $count, PHP_EOL; // 2
echo str_replace('fgh', 'hgf', $str), PHP_EOL; // abcdefGHIjklMnOpQRSTUVWXYZabcdefGHIjklMnOpQRSTUVWXYZ
echo str_ireplace('fgh', 'hgf', $str), PHP_EOL; // abcdehgfIjklMnOpQRSTUVWXYZabcdehgfIjklMnOpQRSTUVWXYZ
这个函数没有什么多说的,第四个参数可能接触到的同学比较少,它返回的是原文中被替换的次数。另外一个 str_ireplace() 是忽略大小写的替换,从下面两行测试代码中就可以看出,fGH 可以直接被我们的小写的 fgh 给替换掉。
补齐、重复字符
补齐字符串,就是在字符串的前后来补上一些字符。
echo str_pad('abc', 10), PHP_EOL; // abc
echo str_pad('abc', 10, '-=', STR_PAD_LEFT), PHP_EOL; // -=-=-=-abc
echo str_pad('abc', 10, '|', STR_PAD_BOTH), PHP_EOL; // |||abc||||
echo str_pad('abc', 4, "*"), PHP_EOL; // abc*
echo str_pad('abc', 2, "*"), PHP_EOL; // abc
如果不给第三个参数的话,默认就是补上空格,另外第四个参数指的是从哪边开始补,默认情况下也是从右边,我们可以设置它为从左边或者从两边。这里需要注意的是,我们在第二个参数填入的字符数量是按整个字符串的数量来规划的,比如最后两条测试代码。如果给定的字符数量是小于原始的字符数量的,那么就不会对这个字符串进行任何操作了。
重复一段字符串内容就比较简单了。
echo str_repeat('abc', 5), PHP_EOL; // abcabcabcabcabc
str_repeat() 根据指定的数量来重复字符串的内容。
其它操作
相对来说,下划线相关的字符串操作函数的功能都比较简单,我们继续看其它的一些操作函数。
分割 csv 格式
print_r(str_getcsv("a,b,c,d"));
// Array
// (
// [0] => a
// [1] => b
// [2] => c
// [3] => d
// )
fgetcsv() 是直接从文件中读取,而 str_getcsv() 是针对于字符串的格式化读取 csv 数据的函数。它后面也有可选的参数,可以指定我们的分隔符号,默认情况下都是以逗号进行分隔的。
偏移字符串
在某些加密算法中,会有一种偏移字符的加密方式,比如我们将正常的字符向后或者向前偏移多少位,像是 a ,在密文中表示为 c ,其实就是让所有的字母向后偏移两位。在 PHP 中,直接提供了一个这样的函数,不过它是固定偏移 13 位的。
echo str_rot13($str), PHP_EOL; // nopqrsTUVwxyZaBcDEFGHIJKLMnopqrsTUVwxyZaBcDEFGHIJKLM
大家可以想想它的应用场景,对于一些加密数据的打乱传输来说,这个功能也是非常有用的哦。
随机打乱字符串
就像 array_shuffle() 一样,字符串中也有这样的一个函数可以随机的对字符串中的内容进行重新排序组合。
echo str_shuffle($str), PHP_EOL; // jaYpZMWIYSbpRacMenQOSGTWTekHlZcdGVVkbOXdHlXUfQnURfIj
分割字符串
对于分割字符串来说,我们最常接触到的是 explode() 这种分割函数,这个函数我们将在后面学习。当然,这个函数的出镜频率也非常高,但是,它是需要一个分割符号的,也就是说,必须要有一个分割符号才能完成对字符串转数组的分割。而我们接下来学习的这个函数,则是根据指定的字符长度来分割的。
print_r(str_split($str, 5));
// Array
// (
// [0] => abcde
// [1] => fGHIj
// [2] => klMnO
// [3] => pQRST
// [4] => UVWXY
// [5] => Zabcd
// [6] => efGHI
// [7] => jklMn
// [8] => OpQRS
// [9] => TUVWX
// [10] => YZ
// )
使用 str_split() 就可以将原始的字符串按第二个参数给定的长度分割成数组了。除了这个之外,还有一个函数也可以按照长度来分割,并且默认会在字符后面加上一些特殊的内容。
echo chunk_split(base64_encode(str_repeat($str, 5)));
// YWJjZGVmR0hJamtsTW5PcFFSU1RVVldYWVphYmNkZWZHSElqa2xNbk9wUVJTVFVWV1hZWmFiY2Rl
// ZkdISWprbE1uT3BRUlNUVVZXWFlaYWJjZGVmR0hJamtsTW5PcFFSU1RVVldYWVphYmNkZWZHSElq
// a2xNbk9wUVJTVFVWV1hZWmFiY2RlZkdISWprbE1uT3BRUlNUVVZXWFlaYWJjZGVmR0hJamtsTW5P
// cFFSU1RVVldYWVphYmNkZWZHSElqa2xNbk9wUVJTVFVWV1hZWmFiY2RlZkdISWprbE1uT3BRUlNU
// VVZXWFlaYWJjZGVmR0hJamtsTW5PcFFSU1RVVldYWVo=
// chunk_split ( string $body , int $chunklen = 76 , string $end = "\r\n" ) : string
从注释中的函数签名可以看出,chunk_split() 函数还有两个默认参数,一个是长度默认为 76 个字符,另一个在每一段的结尾增加什么内容。注意,它返回的不是数组!!!是一个用最后那个 end 内容所分隔的字符串。
单词与单字数量
在很多搜索系统中,我们都会遇到过分词的问题,分词之后可能还要统计这个词出现的频率也就是词频,而对于英文来说,PHP 中直接就提供了这种类似的分词统计函数。毕竟英文本身就是以空格进行隔离单词的,所以它的实现比中文还是简单很多。
echo str_word_count('This is a test.'), PHP_EOL; // 4
print_r(str_word_count('This is a test.', 1));
// Array
// (
// [0] => This
// [1] => is
// [2] => a
// [3] => test
// )
print_r(str_word_count('This is a test.', 2));
// Array
// (
// [0] => This
// [5] => is
// [8] => a
// [10] => test
// )
str_word_count() 默认情况下可以返回每个字符串中的单词数量。如果给定它的第二个参数为 1 的话,那么会将单词放到数组中返回,如果设置为 2 的话,数组的下标就是这个单词首次出现的位置。
print_r(count_chars('This is a test.', 1));
// Array
// (
// [32] => 3
// [46] => 1
// [84] => 1
// [97] => 1
// [101] => 1
// [104] => 1
// [105] => 2
// [115] => 3
// [116] => 2
// )
echo chr(84), PHP_EOL; // T
echo ord('a'), PHP_EOL; // 97
count_chars() 这个函数返回的则是每个字母出现的次数,注意它返回的数组下标对应的是 asc2 码中对应的值。我们可以使用 chr() 查看这个 asc2 码对应的字母是什么,同样,使用 ord() 可以获取一个字母的 asc2 码值。
编码转义
接下来,我们再来学习几个编码转义相关的内容。这一块基本上都是和系统安全相关的内容。对于一个现代化的应用项目来说,用户提交的内容是必不可少的,只要有用户输入,那么必然就会带来各种安全风险问题。不管是 SQL 注入,还是 XSS 攻击之类的,都和字符串的过滤转义有很大的关系。
特殊符号转义
这里的特殊符号其实主要就是指的是针对 SQL 注入而言的内容,也就是我们在早期经常会使用的函数。为什么说是早期呢?我们先看代码。
// 转义字符
echo addslashes("It's my test."), PHP_EOL; // It\'s my test.
echo addcslashes("It's my test.", 'A..z'), PHP_EOL; // \I\t'\s \m\y \t\e\s\t.
addslashes() 这个函数老码农们都不会陌生,在之前配合 MySQL 扩展的时候经常会用到。但是注意,现在框架中已经很少使用了。毕竟现在都是以 PDO 为主了,我们应该尽量使用 PDO 或者 MySQLi 的预编译能力,而尽量少地去自己拼接 SQL 语句参数。当然,这也是符合潮流的,所以说,现在这个函数真的是比较少见到了。
addcslashes() 是 C 语言实现版本,它需要第二个参数,这个参数可以是范围值,就像我们测试代码中的一样,它就是指从 A 到 z 的所有内容都会转义,也就是添加上斜杠。
uu 编码
uu 编码可以看做是一种加密编码格式,可以将字符串转换成我们看不懂的一种编码形式,当然,它也是提供了反解函数的。
$uu = convert_uuencode($str);
echo $uu, PHP_EOL;
// M86)C9&5F1TA):FML36Y/<%%24U155E=865IA8F-D969'2$EJ:VQ-;D]P45)3
// '5%565UA96@``
// `
echo convert_uudecode($uu), PHP_EOL; // abcdefGHIjklMnOpQRSTUVWXYZabcdefGHIjklMnOpQRSTUVWXYZ
HTML 实体编码
最后就是 HTML 实体编码的内容,它们可是预防 XSS 攻击的最有效的手段。
html = htmlspecialchars("<a href='test'>Test</a>");
echo $html, PHP_EOL; // <a href='test'>Test</a>
$html = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $html, PHP_EOL; // <a href='test'>Test</a>
echo htmlspecialchars_decode($html), PHP_EOL; // <a href='test'>Test</a>
echo htmlspecialchars_decode($html, ENT_QUOTES), PHP_EOL; // <a href='test'>Test</a>
$html = htmlentities("<a href='test'>Test</a>");
echo $html, PHP_EOL; // <a href='test'>Test</a>
$html = htmlentities("<a href='test'>Test</a>", ENT_QUOTES);
echo $html, PHP_EOL; // <a href='test'>Test</a>
echo html_entity_decode($html), PHP_EOL; // <a href='test'>Test</a>
echo html_entity_decode($html, ENT_QUOTES), PHP_EOL; // <a href='test'>Test</a>
只要学过一点 PHP 的都知道它们的作用,就是将 < 、& 这些 HTML 中的特殊符号转换成 &xxxx; 这种形式的文本内容。这样,HTML 代码就不会在浏览器中直接运行了。htmlspecialchars() 和 htmlentities() 的功能其实都差不多,只是 htmlentities() 支持的内容更多一些,这个一会我们再讲。它们都有一个可选参数,这里我们设置为了 ENT_QUOTES ,表示的是单引号也编码。关于这个参数的可选常量还有很多,大家可以去官方文档中查阅。
如果设置了这个参数的话,那么使用对应的 htmlspecialchars_decode() 和 html_entity_decode() 进行反转义的时候,也要加上对应的参数常量。这里有个坑,注意 htmlentities() 的反转义函数的名字是 html_entity_decode() 这个哦,不是 htmlentities_decode() 。而 htmlspecialchars_decode() 却是真的只是给 htmlspecialchars() 后面加了个 _decode()。这个命名规范真的是无力吐糟。
网上有很多文章会说 htmlspecialchars() 和 htmlentities() 对于中文的编码会有不同,其实这也是比较老的问题了,在 PHP5.6 之后它们对中文的支持已经没有区别了。
// php5.6后中文没区别
echo htmlspecialchars("<a href='test'>测试</a>"), PHP_EOL;
echo htmlentities("<a href='test'>测试</a>"), PHP_EOL;
而它们两个现在最主的区别就是可以转义的字符范围了。
echo htmlspecialchars("<a href='test'>Ψ</a>"), PHP_EOL; // <a href='test'>Ψ</a>
echo htmlentities("<a href='test'>Ψ</a>"), PHP_EOL; // <a href='test'>Ψ</a>
我们可以通过一个函数来查看它们所支持的编码字符。
print_r(get_html_translation_table(HTML_ENTITIES));
// Array
// (
// ["] => "
// [&] => &
// [<] => <
// [>] => >
// [ ] =>
// [¡] => ¡
// [¢] => ¢
// [£] => £
// [¤] => ¤
// [¥] => ¥
// [¦] => ¦
// [§] => §
// [¨] => ¨
// [©] => ©
// [ª] => ª
// [«] => «
// [¬] => ¬
// [] => ­
// [®] => ®
// [¯] => ¯
// [°] => °
// [±] => ±
// [²] => ²
// [³] => ³
// [´] => ´
// [µ] => µ
// [¶] => ¶
// [·] => ·
// [¸] => ¸
// [¹] => ¹
// [º] => º
// [»] => »
// [¼] => ¼
// [½] => ½
// [¾] => ¾
// [¿] => ¿
// [À] => À
// [Á] => Á
// …………………………
// …………………………
// …………………………
print_r(get_html_translation_table(HTML_SPECIALCHARS));
// Array
// (
// ["] => "
// [&] => &
// [<] => <
// [>] => >
// )
其实在日常的开发过程中,直接使用 htmlspecialchars() 就够了,毕竟我们经常需要的,也是最重要的内容就是这四个。其中两个破折号更是影响安全的重中之重。
总结
今天学习的内容也还只是字符串操作函数中的一小部分,最主的就是 str_ 这些开头的函数。不过相对来说它们比 str 开头的函数还是要少一些。另外我们还学习了一点编码转义部分的内容,这些内容对于我们系统的安全来说非常重要,也是需要大家深入了解掌握的内容。下篇文章将学习的是剩下的一大堆函数名没什么规则的函数,继续加油吧!
测试代码:
参考文档: