# 4. 字串處理與正規表達式 {%hackmd QnyEFBdERZebn4iQDXNPnA %} ## 本章重點:處理使用者的字串輸入 ## 01 字串格式化 ### 修剪字串 - 整理使用者輸入的字串 - trim => 將字串前後的空白字元刪除並回傳結果,與chop()行為類似 - ltrim() => 移除開始處的空白字元 - rtrim() => 移除結尾處的空白字元 ### 格式化字串,以供輸出 - Why篩選字串? - 為了提升安全性(避免被SQL-Injection) - 使用htmlspecialchars()篩選使用者的輸入(避免惡意程式碼被輸出到瀏覽器) - \& => 轉換成 \&amp; - \" => 轉換成 \&quot; - \' => 轉換成 \&apos; - \< => 轉換成 \&lt; - \> => 轉換成 \&gt; - 使用str_replace(),供其他表單做輸出(避免惡意程式碼被輸出到email) - 使用HTML格式:n12br() - 將字串的換行字元(\n)全變成HTML換行字元(\<br />) - 格式化字串以供列印 - echo => 將字串印至瀏覽器 - sprintf() => 會回傳格式化後的字串 - printf() => 會輸出格式化後的字串 - 改變字串的大小寫 - 變大寫 - strtoupper() - string to upper - 變小寫 - strtolower() - string to lower - 若第一個字元是字母,將它轉成大寫 - ucfirst() - 若單字第一個字元是字母,將它們轉成大寫 ## 02 使用字串函式來連結與拆解字串 ### explode(), implode(), join() - explode() => 用來切割文字 - implode ()、join() => explode()逆運算 ```php= $email = 'job_steves@apple.com'; $email_array = explode('@', $email); //$email_array[0]存帳號,$email_array[1]存網域 //$email_array[0]:job_steves,$email_array[1]apple.com $new_email = implode('@', $email_array); //使用第一個參數當作陣列結合條件 ``` ### strtok() - 可以放多個切割符號,做切割 ```php= $string = 'This is\tan example\nstring'; $tok = strtok($string, '\n\t'); #空格,換行,TAB while ($tok !== false) { echo “$tok<br />”; $tok = strtok(” \n\t”); } echo "————-<br />"; /* Output: This is an example string ————- */ ``` ### 使用 substr() - 可以取得部份字串(可以指定開頭與結尾) ```php= $test = "Your customer service is excellent."; substr($test, 1); //our customter service is excellent. substr($str, -9); //excellent substr($test, 0, 4); //Your 0 <= x < 4 substr($test, 5, -13); //customer service //回傳第四個字元與倒數13個字元之間的字元 ``` ## 03 比較字串 ### strcmp(), strcasecmp(), strnatcmp() - strcmp() => 字串比大小,會區分大小寫 ```php= strcmp($a, $b); //$a === $b => if True: return 0 //$a > $b => if True: return 大於零的數字 //$a < $b => if True: return 小於零的數字 //若要匹配相同,注意要寫成: $a = 'omg'; $b = 'omg'; if(!strcmp($a, $b)){ //如果相同 echo "They are the same" } ``` - strcasecmp() => 幾乎與strcmp()相同,差異是他不區分大小寫 - strnatcmp() => 與strcasecmp()相同點在:按照自然順序比較字串 ### 如何確認字串長度? - 使用strlen() ```php= echo strlen('hello'); //5 ``` ## 04 使用字串函式來匹配與替換字串 - 檢查字串裡有沒有某個特定的子字串 ### 找尋字串中的字串 - strstr() ```php= strstr($feedback, 'shop'); //檢查$feedback變數裡,是否有shop這個字串? //若有,回傳從shop後的內容(含shop);若否,回傳false //stristr()是strstr()的其他版本,不區分大小寫 //strrchr也是strstr()的其他版本,會回傳關鍵字最後一個出現之後的部分 ``` - strchr() ### 尋找子字串的位置 - strpos() => string position ```php= $test = "Hello world"; echo strpos($test, "o"); //4 echo strpos($test, "o", 5); //7,因為從位置5開始查找 ``` - strrpos() - 與strpos()幾乎相同,但它會回傳關鍵字在字串裡最後一次出現的位置 ### 替換子字串 - str_replace() => 依關鍵字做替換 ```php= $feedback_no_color_words = str_replace($offcolor, '%!@*', $feedback); //$offcolor => 被取代 //'%!@*' => 取代$offset //$feedback => 查找的字串 ``` - substr_replace() => 依位置做替換 ```php= $test = substr_replace($text, 'X', -1); //將$test最後一個字元換成"X" ``` ## 05 介紹正規表達式 - 一種描述一段文字的方法 ### 基礎 - 類似strstr() ### 分隔符號(一定要使用) => /[xxxx]/ - /shop/ => 匹配shop - /http:\\/\\// => 想要匹配"/"的狀況 - #http://# => 可選擇不同的分隔符號 - /shop/i => 模式修飾符號 ### 字元類別與型態 - \. => 萬用字元 - /[a-z]at/ => 限制只有a-z - /[^a-z]/ => 不能是z-z - 預定義字元類別:[[:alpha:]1-5] => 可包含任何字母或1-5任何數字 ### 重複 - \* => 0 或 多次 - \+ => 重複 一 或 多次 - \? => 一次 或 不出現 ### 子表達式 - /(very )*large/ - 可以匹配"large", "very large", "very very large" ### 多次出現的子表達式 - /(very ){1,3}/ - 可以匹配 "very ", "very very ", "very very very " ### 錨定開頭或結尾 - /^bob/ => 開頭是bob - /com$/ => 結尾是com - /\^[a-z]$/ => 匹配a-z,只有一個字 ## 06 使用正規表達式尋找子字串 - preg_match() ## 07 使用正規表達式替換子字串 - preg_replace() ## 08 使用正規表達式分割字串 ### preg_split() - 適合分割email地址、網域、日期 ```php= $address = 'username@example.com'; $arr = preg_split('/\.|@/', $address);//使用or,用.與@做切割 while(list($key, $value) = each($arr)){ echo '<br />'.$value; } //Output: username, example, com ```