一、字符串操作
1.字符串的格式化
1.1 干掉空格
trim()函數可以除去字符串開始位置和結束位置的空格,並將結果字符串返回。
ltrim()函數可以除去字符串開始位置的空格。
rtrim()函數可以除去字符串結束位置的空格。
1.2 格式化字符串以便顯示
nl2br()函數將字符串作為輸入參數,用HTML中的<br />標記代替字符串中的換行符。
printf()函數將一個格式化的字符串輸出到浏覽器中。
sprintf()函數返回一個格式化了的字符串。
當在類型轉換代碼中使用printf()函數時,可以使用帶序號的參數方式,就是說,參數的順序不一定要與轉換說明中的順序相同。
printf(“Total aount of order is %2\$.2f(with shipping %1\.2f)”, $total_shipping,$total);
strtoupper()函數將字符串轉換為大寫。
strtolower()函數將字符串轉換為小寫。
ucfirst()函數將第一個字符轉換為大寫(如果是字母的話)。
ucwords()函數將字符串每個單詞的第一個字母轉換為大寫。
1.3 格式化字符串以便存儲
當將數據插入到數據庫中的時候可能會引起一些問題,因為數據庫會將這些字符解釋成控制符。這些有問題的字符就是引號(單引號,雙引號)、反斜槓和NULL字符。為了將這些字符進行轉義處理,可以在它們前面加一個反斜槓。PHP提供了兩個專門用於轉義字符串的函數。
PHP配置將自動添加或去除反斜槓。這個功能是由magic_quotes_gpc配置指令控制的。新版本默認啟用。
如果啟用,必須調用stripslashes()函數移除這些反斜槓;否則應該使用addslashes()將它們重新格式化,所有引號將被加上反斜槓。
2.用字符串函數連接和分割字符串
2.1 分割與組合
explode()函數把字符串分割為數組。
explode(separator,string,limit)
separator:根據什麼分割
string:要分割的字符串
limit:返回數組元素的最大數目(可選)
如果域名是大寫的或者大小寫混合的,這個函數就無法正常使用。可以通過將域名轉換成全是大寫或小寫的方法來避免這個問題。
implode()函數把數組元素組合為一個字符串。join()函數是它的別名。
implode(separator,array)
separator:數組元素之間放置的內容
array:要結合為字符串的數組
2.2 繼續分割
strtok()函數把字符串分割成更小的字符串。
strtok(string,split)
string:規定要分割的字符串
split:規定一個或多個分割字符
2.3 截取
substr()函數返回字符串的一部分。
substr(string,start,length)
string:必需。規定要返回其中一部分的字符串。
start:必需。規定在字符串的何處開始。
正數 - 在字符串的指定位置開始
負數 - 在從字符串結尾的指定位置開始
0 - 在字符串中的第一個字符處開始
length:可選。規定要返回的字符串長度。默認是直到字符串的結尾。
正數 - 從 start 參數所在的位置返回
負數 - 從字符串末端返回
3.字符串的比較
strcmp()的函數原型如下所示:
int strcmp(string str1, string str2);
如果這兩個字符串相等,該函數就返回0,如果按字典順序str1在str2後面(大於str2)就返回一個正數,如果str1小於str2就返回一個負數。這個函數是區分大小的。
strcasecmp()除了不區分大小寫之外,其他和strcmp()一樣。
strnatcmp()及與之對應的不區分大小寫的strnatcasecmp()將按“自然排序”比較字符串。
strlen()函數可以檢查字符串的長度。
4.使用字符串函數匹配和替換子字符串
4.1 在字符串中找字符串
函數strstr()可以用於在一個較長的字符串中查找匹配的字符串或字符。
string strstr(源字符串,目標子字符串);
如果找到了目標關鍵字的一個精確匹配,函數將會從目標關鍵字前面返回被搜索的字符串,否則返回值為false。如果存在不止一個目標關鍵字,返回的字符串從出現第一個目標關鍵字的位置開始。
函數strstr()有兩個變體。一個是stristr(),不區分大小寫。另一個是strrchr(),會從最後出現目標關鍵字的位置的前面返回被搜索字符串。
4.2 查找子字符串的位置
函數strpos()返回目標關鍵字子字符串在被搜索字符串中的位置。相比strstr()函數運行速度更快。
int strpos(string haystack, string needle, int [ offset]);
該函數的可選參數offset是用來指定被搜索字符串的開始搜索位置。
函數strrpos()也幾乎是一樣的,但返回的是被搜索字符串中最後一次出現目標關鍵字子字符串的位置。
在任何情況下,如果目標關鍵字不在字符串中,strpos()或strrpos()都將返回false。因此,這就可能帶來新的問題,因為false在一個如PHP這樣的弱類型語言中等於0,也就是說字符串的第一個字符。
可以使用運算符“===”來測試返回值,從而避免這個問題:
$result = strpos($test, "H"); if($result === false){ echo "Not found"; } else{ echo "Found at position ".$result; }
4.3 替換子字符串
str_replace():
mixed str_replace(mixed needle, mixed new_needle, mixed haystack[, int & count]);
四個參數依次對應:原子字符串、新子字符串、源字符串,要執行的替換操作次數(可選)。
函數substr_replace()則用來在給定位置中查找和替換字符串中特定的子字符串。
string substr_replace(string string, string 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:]] 文字數字字符 [[:alpha:]] 字母字符 [[:lower:]] 小寫字母 [[:upper:]] 大寫字母 [[:digit:]] 小數 [[:xdigit:]] 十六進制數字 [[:punct:]] 標點符號 [[:blank:]] 制表符和空格 [[:space:]] 空白字符 [[:cntrl:]] 控制符 [[:print:]] 所有可打印的字符 [[:graph:]] 除空格外所有可打印的字符
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正則表達式中,用於方括號外面的特殊字符(在括號外面需要轉義的):
\ 轉義字符 ^ 在字符串開始匹配 $ 在字符串末尾匹配 . 匹配除換行符(\n)之外的字符 | 選擇分支的開始 ( 子模式的開始 ) 子模式的結束 * 重復0次或更多次 + 重復1次或更多次 { 最小/最大量記號的開始 } 最小/最大量記號的開始 ? 標記一個子模式為可選的
在POSIX正則表達式中,用於方括號裡面的特殊字符(在括號裡面需要轉義的):
\ 轉義字符 ^ 非,僅用在開始位置 - 用於指明字符范圍
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 ereg(string pattern, string search, array [matches]);
該函數搜索字符串search,在pattern中尋找與正則表達式相匹配的字符串。如果發現了與pattern的子表達式相匹配的字符串,這些字符串將會存儲在數組matches中,每個數組元素對應一個子表達式。
函數eregi()除了不區分大小寫外,其他與ereg()一樣。
驗證郵箱:
if(!eregi('^[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$',$email)){ echo "<p>郵箱格式錯誤。</p>"; exit; }
7.用正則表達式替換子字符串
ereg_replace():
string ereg_replace(string pattern, string replacement, string search);
該函數在字符串search中查找正則表達式pattern的字符串,並且用字符串replacement來替換。
函數eregi_replace()不區分大小寫。
8.使用正則表達式分割字符串
split():
array split(string pattern, string search[, int max]);
函數將字符串search分割成符合正則表達式模式的子字符串,然後將子字符串返回到一個數組中。
$address = “[email protected]”; $arr = split(“\.|@”,$address); while(list($key, $value) = each($arr)){ echo “<br />”.$value; }
然後發現了一個報錯:
這個問題是版本原因造成的:
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後:
$address = "[email protected]"; $arr = preg_split("/[\.|@]+/", $address); while(list($key, $value) = each($arr)){ echo "<br />".$value; }
寫到這裡略感悲劇,原著中本章的後半段介紹的都是POSIX Regex。PCRE Regex有時間會補更,希望了解關於PCRE的內容,可以閱讀在線手冊:http://www.php.net/pcre。
9.總結
一般而言,對於同樣的功能,正則表達式函數運行效率要低於字符串函數。如果應用程序足夠簡單,那麼就用字符串表達式。
但是,對於可以通過單個正則表達式執行的任務來說,如果使用多個字符串函數,則是不推薦的。
整理自《PHP和MySQL Web開發》第四版