2012-05-23

Java 腦袋學 PHP String

PHP String 預設是用 ASCII 編碼,所以 php 檔案中若有直接使用中文,檔案編碼得用 UTF-8 或者 MS950,有中文的檔案是無法使用 ASCII 或者 ISO-8859-1 存檔的;至於外面傳進來的中文,或者是網頁要顯示中文,改天再說。

Create

建立字串的三種方式
$s = '單引號';

或者

$s = "雙引號";

或者

$s = <<< TEXT
heredoc
TEXT;

使用單引號建立字串只需要注意兩個特殊字元,即單引號本身以及反斜線,要用「\'」或者「\\」才能顯示單引號或反斜線,但特別的是像 \n、\t 之類的特殊字元卻會直接以文字方式呈現。

使用雙引號建立字串就神奇了,除了認得特殊字元(\n、\r、\t)外,還會整合變數,若是用單引號,就得用「.」串接。
$oldSkill = 'Java';
$newSkill = 'PHP';
$s = "Learn $newSkill using $oldSkill brain";
$s = 'Learn '.$newSkill.' using '.$oldSkill.' brain';
整合變數除了一般的變數外,還可以使用陣列或者物件屬性。
$s = "$array[3] and $obj->value";
整合變數對於關聯陣列有特殊的限制,key 值不可以加單引號,若要加單引號,整個變數要用大括弧包起來;大括弧也可以用在一般變數和物件屬性上。
$s = "$array[one] or {$array['one']}";
因為雙引號認得變數,所以「$」在雙引號裡就成為特殊字元,要輸出雙引號得用反斜線「\$」,另外雙引號與反斜線也要特別處理:「\"」與「\\」。

使用 heredoc 建立字串就神奇到極致了,不僅認得特殊字元(\n、\r、\t),也會整合變數,甚至把單引號、雙引號與反斜線都當成一般字元,不用加反斜線處理,只有「$」要加反斜線處理。

因為不用特別處理單引號與雙引號的特質,且會整合變數,heredoc 最適合用來輸出 HTML。

heredoc 語法特點:
  • 起點:以三個小於字元「<<<」接一個 token,「<<<」與 token 之間可以有空白,但是要在同一行,token 之後換行,不可以有其他內容。
  • 內容:什麼都可以。
  • 第一種終點:該 heredoc 作為變數的宣告,token 在換行後的第一個字元,token 之後接分號,分號後換行,不可以有其他內容,也就是該行只有該 token 與分號,其他什麼都沒有,空白也不行。
$s = <<< TEXT heredoc
TEXT;
  • 第二種終點:該 heredoc 作為字串的連接,也就是後面用「.」連接其他字串,在這種情形下,token 在換行後的第一個字元,token 之後換行,不可以有其他內容,也就是該行只有該 token,其他什麼都沒有,空白也不行,連接字串的「.」得在另一行,不可以與 token 同一行。
$s = <<< TEXT heredoc
TEXT
.' more...';
字串連接是用「.」
$s =  "Learn $newSkill "."using $oldSkill";

Read

判斷一個變數是不是字串
if (is_string($var)) { .. }
讀取單一字元(charAt)
$s = 'Java Artisan';
print $s[3];

或者

print $s{3};
可以像陣列一樣,對字串使用中括弧,或者為了與陣列做區別,也可以使用大括弧。

取得字串長度(length)
$length = strlen($s);

取得子字串在字串中的位置(indexOf)
if (strpos($email, '@') === false) { ... }
若子字串不存在字串中,回傳 false,不是回傳 -1,要小心在 PHP 裡,0 == false 為 true。

取得部份字串(substring)
$ss = substr($string, $start, $length);
若 $start 超過字串的長度,回傳 false;若 $start 加上 $length 超過字串的長度,等同於沒有輸入 $length 一樣,回傳 $start 到結束。
若 $start 為負值,從字串末端算回來,但不像正值從零算成,負值是從 1 算起;若從末端算起,且超過字串起點,不像正值回傳 false,而是視同 $start 為 0。
若 $length 為負值,像負值的 $start 一樣,從字串末端算回來的位置,但不像負值的 $start 是從 1 算起,而是從 0 算起。


Update

取代字串 (replace)
$ss = str_replace($search, $replace, $string);
取代子字串(replace)
$ss = substr_replace($string, $new_string, $start, $length);
神奇的 $start 與 $length 用法同 substr;特別的是若 $start 與 $length 皆為 0,則將新字串塞到舊字串的前方,若 $start 超過字串長度,不是回傳 false,而是將新字串接到舊字串後方。好用的技巧:
$ss = substr_replace($title, '...', 15);

顯示標題時,超過 15 的字元的截掉並補上...,若沒超過,則完整顯示(StringUtils.abbreviate())。

以指定寬度將字串斷行
wordwrap($string) ;
wordwrap 預設每行 75 個字元,可以在第二個參數做修改;預設的斷行字元為「\n」,可以使用第三個參數指定斷行的方式,如「
」。

不幸的是對中文無用,雖然可以加上第四個參數「true」強迫斷字,但因為 wordwrap 是以 byte 計算,不是以字元計算,所以有些斷字會變成亂碼。

大小寫轉換
ucfirst($string);

ucwords($string);

strtolower($string);

strtoupper($string);
ucfirst 將字串第一個字元轉成大寫,其他字串不動;ucwords 將字串裡每一個單字的第一個字母轉大寫,其餘字母不動。

一定要有的 trim
ltrim($s);
rtrim($s);
trim($s);
三個 trim 都可以加上第二個參數,用來指定要 trim 掉的字元,可以同時指定多個字元,或用「..」表示範圍。
trim($s, '123');

trim($s, '1..3');
 字串前後的 1 或 2 或 3 都會被 trim 掉。

chop 與 rtrim 是一樣的功能。


Advance

將字串分割成陣列
$array = explode(' ', $string);
另外還有一個 str_split,可以依指定的長度將字串切成陣列。
$array = split(' +', $string);
$array = preg_split('/ +/', $string);
splitpreg_split 都是用 Regular Expression 來切字串,split 已經被 deprecated,建議使用 preg_split。

將陣列接成字串
$string = implode(' ', $array);
將陣列輸出成 csv 格式字串
$a = ...; // 二維陣列
$h = fopen('php://output', 'w');
foreach ($a as $l) {
fputcsv($h, $l);
}
fclose($h);
不建議使用 implode,因為 implode 沒有處理字串中的逗號。

將 csv 字串解析成陣列
$h = fopen('csv.csv', 'r') or die("Can't open csv.csv");
while ($a = fgetcsv($h)) {
print_r($a);
}
fclose($h) or die("Can't close csv.csv");
不建議使用 explode,因為 explode 沒有處理字串中的逗號。

產生固定寬度的字串
pack('A5A2', '123', 'ab');
pack 只會用空白做 pad,過長的字串會截斷。
str_pad(substr($string, 0, 5), 5, '.');
str_pad 比較有彈性,可以指定 pad 字元,也可以加入第四個參數指定 right pad(預設,STR_PAD_RIGHT)或 left pad(STR_PAD_LEFT)或 STR_PAD_BOTH(怎麼 pad?),但是不會截斷過長字串,可以搭配 substr 使用。

解析固定寬度的字串
$array = unpack('A5titleA2key', $string);
unpack 回傳一個有 title 與 key 的關聯陣列,也可以用 substr 做苦工。

沒有留言:

張貼留言