一、字符串操作
1.字符串的格式化
1.1 干掉空格
trim()函数可以除去字符串开始位置和结束位置的空格,并将结果字符串返回。
ltrim()函数可以除去字符串开始位置的空格。
rtrim()函数可以除去字符串结束位置的空格。
1.2 格式化字符串以便显示
nl2br()函数将字符串作为输入参数,用HTML中的
标记代替字符串中的换行符。
printf()函数将一个格式化的字符串输出到浏览器中。
sprintf()函数返回一个格式化了的字符串。
当在类型转换代码中使用printf()函数时,可以使用带序号的参数方式,就是说,参数的顺序不一定要与转换说明中的顺序相同。
<span style="color: #008080;">printf</span>(“Total aount of order is %2\$.2f(with shipping %1\.2f)”, <span style="color: #800080;">$total_shipping</span>,<span style="color: #800080;">$total</span>);
strtoupper()函数将字符串转换为大写。
strtolower()函数将字符串转换为小写。
ucfirst()函数将第一个字符转换为大写(如果是字母的话)。
ucwords()函数将字符串每个单词的第一个字母转换为大写。
1.3 格式化字符串以便存储
当将数据插入到数据库中的时候可能会引起一些问题,因为数据库会将这些字符解释成控制符。这些有问题的字符就是引号(单引号,双引号)、反斜杠和NULL字符。为了将这些字符进行转义处理,可以在它们前面加一个反斜杠。PHP提供了两个专门用于转义字符串的函数。
PHP配置将自动添加或去除反斜杠。这个功能是由magic_quotes_gpc配置指令控制的。新版本默认启用。
如果启用,必须调用stripslashes()函数移除这些反斜杠;否则应该使用addslashes()将它们重新格式化,所有引号将被加上反斜杠。
2.用字符串函数连接和分割字符串
2.1 分割与组合
explode()函数把字符串分割为数组。
<span style="color: #008080;">explode</span>(separator,<span style="color: #0000ff;">string</span>,limit)
separator:根据什么分割
string:要分割的字符串
limit:返回数组元素的最大数目(可选)
如果域名是大写的或者大小写混合的,这个函数就无法正常使用。可以通过将域名转换成全是大写或小写的方法来避免这个问题。
implode()函数把数组元素组合为一个字符串。join()函数是它的别名。
<span style="color: #008080;">implode</span>(separator,<span style="color: #0000ff;">array</span>)
separator:数组元素之间放置的内容
array:要结合为字符串的数组
2.2 继续分割
strtok()函数把字符串分割成更小的字符串。
<span style="color: #008080;">strtok</span>(<span style="color: #0000ff;">string</span>,<span style="color: #008080;">split</span>)
string:规定要分割的字符串
split:规定一个或多个分割字符
2.3 截取
substr()函数返回字符串的一部分。
<span style="color: #008080;">substr</span>(<span style="color: #0000ff;">string</span>,start,length)
string:必需。规定要返回其中一部分的字符串。
start:必需。规定在字符串的何处开始。
正数 - 在字符串的指定位置开始
负数 - 在从字符串结尾的指定位置开始
0 - 在字符串中的第一个字符处开始
length:可选。规定要返回的字符串长度。默认是直到字符串的结尾。
正数 - 从 start 参数所在的位置返回
负数 - 从字符串末端返回
3.字符串的比较
strcmp()的函数原型如下所示:
int <span style="color: #008080;">strcmp</span>(<span style="color: #0000ff;">string</span> str1, <span style="color: #0000ff;">string</span> str2);
如果这两个字符串相等,该函数就返回0,如果按字典顺序str1在str2后面(大于str2)就返回一个正数,如果str1小于str2就返回一个负数。这个函数是区分大小的。
strcasecmp()除了不区分大小写之外,其他和strcmp()一样。
strnatcmp()及与之对应的不区分大小写的strnatcasecmp()将按“自然排序”比较字符串。
strlen()函数可以检查字符串的长度。
4.使用字符串函数匹配和替换子字符串
4.1 在字符串中找字符串
函数strstr()可以用于在一个较长的字符串中查找匹配的字符串或字符。
<span style="color: #0000ff;">string</span> <span style="color: #008080;">strstr</span>(源字符串,目标子字符串);
如果找到了目标关键字的一个精确匹配,函数将会从目标关键字前面返回被搜索的字符串,否则返回值为false。如果存在不止一个目标关键字,返回的字符串从出现第一个目标关键字的位置开始。
函数strstr()有两个变体。一个是stristr(),不区分大小写。另一个是strrchr(),会从最后出现目标关键字的位置的前面返回被搜索字符串。
4.2 查找子字符串的位置
函数strpos()返回目标关键字子字符串在被搜索字符串中的位置。相比strstr()函数运行速度更快。
int <span style="color: #008080;">strpos</span>(<span style="color: #0000ff;">string</span> haystack, <span style="color: #0000ff;">string</span> needle, int [ offset]);
该函数的可选参数offset是用来指定被搜索字符串的开始搜索位置。
函数strrpos()也几乎是一样的,但返回的是被搜索字符串中最后一次出现目标关键字子字符串的位置。
在任何情况下,如果目标关键字不在字符串中,strpos()或strrpos()都将返回false。因此,这就可能带来新的问题,因为false在一个如PHP这样的弱类型语言中等于0,也就是说字符串的第一个字符。
可以使用运算符“===”来测试返回值,从而避免这个问题:
<span style="color: #800080;">$result</span> = <span style="color: #008080;">strpos</span>(<span style="color: #800080;">$test</span>, "H"<span style="color: #000000;">); </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$result</span> === <span style="color: #0000ff;">false</span><span style="color: #000000;">){ </span><span style="color: #0000ff;">echo</span> "Not found"<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span><span style="color: #000000;">{ </span><span style="color: #0000ff;">echo</span> "Found at position ".<span style="color: #800080;">$result</span><span style="color: #000000;">; }</span>
4.3 替换子字符串
str_replace():
<span style="color: #0000ff;">mixed</span> <span style="color: #008080;">str_replace</span>(<span style="color: #0000ff;">mixed</span> needle, <span style="color: #0000ff;">mixed</span> new_needle, <span style="color: #0000ff;">mixed</span> haystack[, int & <span style="color: #008080;">count</span>]);
四个参数依次对应:原子字符串、新子字符串、源字符串,要执行的替换操作次数(可选)。
函数substr_replace()则用来在给定位置中查找和替换字符串中特定的子字符串。
<span style="color: #0000ff;">string</span> <span style="color: #008080;">substr_replace</span>(<span style="color: #0000ff;">string</span> <span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span> replacement, int start, int [length]);
这个函数使用字符串replacement替换字符串string中的一部分。
二、正则表达式
5.正则表达式的介绍
5.1 科普
正则表达式是一种描述一段文本模式的方法。
正则是在一个字符串的某个位置匹配另一个字符串。除了精确匹配字符外,还可以用特殊字符来指定表达式的元意。
下面我们来介绍POSIX风格的正则。
5.2 字符集和类
字符集可以用于匹配属于特性类型的任何字符;事实上它们是一种通配符。
可以用字符作为一个通配符来代替除换行符(\n)之外的任一个字符:
.at
如果要限定它是a到z之间的字符:
[a-z]at
任何包含在方括号([])中的内容都是一个字符类(一个呗匹配字符所属的字符集合)。注意,方括号中的表达式只匹配一个字符。
可以列出一个集合:
[aeiou]
也可以描述一个范围:
[a-zA-Z]
还可以用集合来指明字符不属于某个集:
[^a-z]
当把脱字符号(^)包括在方括号里面时,表示否。
许多预定义字符类也可以在正则表达式中使用。
[[:alnum:<span style="color: #000000;">]] <span style="color: #000080;">文字数字字符</span> [[</span>:alpha:<span style="color: #000000;">]] <span style="color: #000080;">字母字符</span> [[</span>:lower:<span style="color: #000000;">]] <span style="color: #000080;">小写字母</span> [[</span>:upper:<span style="color: #000000;">]] <span style="color: #000080;">大写字母</span> [[</span>:digit:<span style="color: #000000;">]] <span style="color: #000080;">小数</span> [[</span>:xdigit:<span style="color: #000000;">]] <span style="color: #000080;">十六进制数字</span> [[</span>:punct:<span style="color: #000000;">]] <span style="color: #000080;">标点符号</span> [[</span>:blank:<span style="color: #000000;">]] <span style="color: #000080;">制表符和空格</span> [[</span>:space:<span style="color: #000000;">]] <span style="color: #000080;">空白字符</span> [[</span>:cntrl:<span style="color: #000000;">]] <span style="color: #000080;">控制符</span> [[</span>:<span style="color: #0000ff;">print</span>:<span style="color: #000000;">]] <span style="color: #000080;">所有可打印的字符 </span> [[</span>:graph:]] <span style="color: #000080;">除空格外所有可打印的字符</span>
5.3 重复
符号“*”表示这个模式可以被重复0次或更多次,符号“+”则表示这个模式可以被重复1次或更多次:
[[:alnum:]]+
表示“至少有一个字母字符”。
5.4 子表达式
使用圆括号可以表示“至少这些字符串中的一个需要精确匹配”:
(very)*large
可以匹配“large”、“very large”、“very very large”等。
5.5 子表达式计数
可以用在花括号中的数字表达式来指定内容允许重复的次数。{3}表示重复3次,{2,4}表示重复2-4次,{2,}表示至少重复两次:
(very){1,3}
表示匹配“very”、“very very”和“very very very”。
5.6 定位到字符串的开始或末尾
脱字符号(^)用于正则表达式开始,表示子字符串必须出现在被搜索字符串的开始处,字符“$”用于正则表达式的末尾,表示子字符串必须出现在字符串的末尾。
这个模式将匹配只包含a到z之间一个字符的字符串:
^[a-z]$
5.7 分支
可以使用正则表达式中的一条竖线来表示一个选择。
com|edu|net
5.8 匹配特殊字符
如果要匹配前面提到过的特殊字符,如点号、大括号或者美元符,就必须在它们前面加一个反斜杠。如果要匹配一个反斜杠,那就用两个反斜杠。
在PHP中,必须将正则表达式模式包括在一个单引号字符串中。使用双引号引用的正则表示式将带来一些不必要的复杂性。
5.9 特殊字符整理
在POSIX正则表达式中,用于方括号外面的特殊字符(在括号外面需要转义的):
<span style="color: #000000;">\ <span style="color: #000080;">转义字符 </span></span>^<span style="color: #000000;"><span style="color: #000080;"> 在字符串开始匹配</span> $ <span style="color: #000080;">在字符串末尾匹配 </span></span>.<span style="color: #000080;"> 匹配除换行符(\n)之外的字符 </span>|<span style="color: #000000;"><span style="color: #000080;"> 选择分支的开始</span> ( <span style="color: #000080;">子模式的开始</span> ) <span style="color: #000080;">子模式的结束 </span></span>*<span style="color: #000080;"> 重复0次或更多次 </span>+<span style="color: #000000;"><span style="color: #000080;"> 重复1次或更多次</span> { <span style="color: #000080;">最小</span></span><span style="color: #000080;">/</span><span style="color: #000000;"><span style="color: #000080;">最大量记号的开始</span> } <span style="color: #000080;">最小</span></span><span style="color: #000080;">/最大量记号的开始 </span>? <span style="color: #000080;">标记一个子模式为可选的</span>
在POSIX正则表达式中,用于方括号里面的特殊字符(在括号里面需要转义的):
<span style="color: #000000;">\ <span style="color: #000080;">转义字符 </span></span>^<span style="color: #000080;"> 非,仅用在开始位置 </span>- <span style="color: #000080;">用于指明字符范围</span>
5.10 在智能表单中应用
第一种用途是在顾客的反馈中查找特定的名词。 如果使用一个正则表达式,就可以同时匹配若干个:
shop|customer service|retail
第二个用途是验证程序中用户的电子邮件地址:
^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$
为什么加斜杠请对照5.9中的说明。
6.用正则表达式查找子字符串
查找子字符串是正则表达式的主要应用。在PHP中,可以使用的并且用于匹配POSIX风格正则表达式的两个函数是ereg()和eregi()。
int <span style="color: #008080;">ereg</span>(<span style="color: #0000ff;">string</span> pattern, <span style="color: #0000ff;">string</span> search, <span style="color: #0000ff;">array</span> [matches]);
该函数搜索字符串search,在pattern中寻找与正则表达式相匹配的字符串。如果发现了与pattern的子表达式相匹配的字符串,这些字符串将会存储在数组matches中,每个数组元素对应一个子表达式。
函数eregi()除了不区分大小写外,其他与ereg()一样。
验证邮箱:
<span style="color: #0000ff;">if</span>(!<span style="color: #008080;">eregi</span>('^[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$',<span style="color: #800080;">$email</span><span style="color: #000000;">)){ </span><span style="color: #0000ff;">echo</span> "<p>邮箱格式错误。</p>"<span style="color: #000000;">; </span><span style="color: #0000ff;">exit</span><span style="color: #000000;">; }</span>
7.用正则表达式替换子字符串
ereg_replace():
<span style="color: #0000ff;">string</span> <span style="color: #008080;">ereg_replace</span>(<span style="color: #0000ff;">string</span> pattern, <span style="color: #0000ff;">string</span> replacement, <span style="color: #0000ff;">string</span> search);
该函数在字符串search中查找正则表达式pattern的字符串,并且用字符串replacement来替换。
函数eregi_replace()不区分大小写。
8.使用正则表达式分割字符串
split():
<span style="color: #0000ff;">array</span> <span style="color: #008080;">split</span>(<span style="color: #0000ff;">string</span> pattern, <span style="color: #0000ff;">string</span> search[, int <span style="color: #008080;">max</span>]);
函数将字符串search分割成符合正则表达式模式的子字符串,然后将子字符串返回到一个数组中。
<span style="color: #800080;">$address</span> = “username@example.<span style="color: #000000;">com”; </span><span style="color: #800080;">$arr</span> = <span style="color: #008080;">split</span>(“\.|@”,<span style="color: #800080;">$address</span><span style="color: #000000;">); </span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">list</span>(<span style="color: #800080;">$key</span>, <span style="color: #800080;">$value</span>) = <span style="color: #008080;">each</span>(<span style="color: #800080;">$arr</span><span style="color: #000000;">)){ </span><span style="color: #0000ff;">echo</span> “<br>”.<span style="color: #800080;">$value</span><span style="color: #000000;">; }</span>
然后发现了一个报错:
这个问题是版本原因造成的:
PHP 5.3.0 之后的regex, 希望使用PCRE 的规格, POSIX Regex 都不建议使用了(统一Regex, 避免规格太多?).
所以下述是不建议使用的Function (POSIX), 与建议替换成的Function (PCRE) 列表, 详可见: PHP: Differences from POSIX regex
* POSIX → PCRE
* ereg_replace() → preg_replace()
* ereg() → preg_match()
* eregi_replace() → preg_replace()
* eregi() → preg_match()
* split() → preg_split()
* spliti() → preg_split()
* sql_regcase() → No equivalent
换成PCRE后:
<span style="color: #800080;">$address</span> = "username@example.com"<span style="color: #000000;">; </span><span style="color: #800080;">$arr</span> = <span style="color: #008080;">preg_split</span>("/[\.|@]+/", <span style="color: #800080;">$address</span><span style="color: #000000;">); </span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">list</span>(<span style="color: #800080;">$key</span>, <span style="color: #800080;">$value</span>) = <span style="color: #008080;">each</span>(<span style="color: #800080;">$arr</span><span style="color: #000000;">)){ </span><span style="color: #0000ff;">echo</span> "<br>".<span style="color: #800080;">$value</span><span style="color: #000000;">; }</span>
写到这里略感悲剧,原著中本章的后半段介绍的都是POSIX Regex。PCRE Regex有时间会补更,希望了解关于PCRE的内容,可以阅读在线手册:http://www.php.net/pcre。
9.总结
一般而言,对于同样的功能,正则表达式函数运行效率要低于字符串函数。如果应用程序足够简单,那么就用字符串表达式。
但是,对于可以通过单个正则表达式执行的任务来说,如果使用多个字符串函数,则是不推荐的。
整理自《PHP和MySQL Web开发》第四版