# 4. 字串處理與正規表達式
{%hackmd QnyEFBdERZebn4iQDXNPnA %}
## 本章重點:處理使用者的字串輸入
## 01 字串格式化
### 修剪字串
- 整理使用者輸入的字串
- trim => 將字串前後的空白字元刪除並回傳結果,與chop()行為類似
- ltrim() => 移除開始處的空白字元
- rtrim() => 移除結尾處的空白字元
### 格式化字串,以供輸出
- Why篩選字串?
- 為了提升安全性(避免被SQL-Injection)
- 使用htmlspecialchars()篩選使用者的輸入(避免惡意程式碼被輸出到瀏覽器)
- \& => 轉換成 \&
- \" => 轉換成 \"
- \' => 轉換成 \'
- \< => 轉換成 \<
- \> => 轉換成 \>
- 使用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
```