PHP1:echo、變數、常量

主題:PHP教學
作者:宥晰
PHP (Hypertext Preprocessor)

PHP的功能主要有兩個:1、與使用者互動,2、與資料庫互動。

此互動發生在伺服器端(使用者端的互動一般是使用javascript)。這裡所謂的互動就是交換資料,在php中使用者通常是使用表單或是網址列傳達資訊給伺服器,而伺服器則以新的網頁頁面來做為回應。

換言之,php算是伺服器裡的一個「造網頁」+「查資料庫」的程式。

宣告方式:

<?php
..(PHP
程式碼)
?>

<?

PHP
..(PHP
程式碼)
?>

<?
..(PHP程式碼)
?>

<script language=”PHP”>
..(PHP
程式碼)
</script>

常用的方式就這兩種<?……?>」、「<?php……?>;另外,要使用「<?……?>」這種表示法,必需php.ini檔案內容中的的以下這行 short_open_tag = On」設定為”on”才可以使用。( 通常預設是on,不過Xampp預設是off )

一旦進入<?php……?>(進入PHP結界)必需用使php的語法。所有在php裡的運算都發生在伺服器裡,過程中使用者並不會接收到任何頁面(雖然運算時間通常極短),當伺服器運算後並且造好頁面才會將整個頁面傳 送給使用者。

註:php預設會開啟輸出緩存,如同預設先執行了ob_start()指令,因此所有的輸出內容都將一起送到使用者端(執行效率較高)。若不想開啟緩存,要讓程式出輸內容直接傳給使用者的話,可以修改php.ini檔:implicit_flush=on
//
預設是OFF
或者,腳本一開始就先執行「ob_end_clean();指令。

然而,造頁面就需要打印網頁語法(即打印HTMLJSCSS)以供使用者端的瀏覽器讀取,打印程式碼的的主要指令是「echo

1echo也可以換 print 字串 功能一樣;唯print有回傳值而echo沒有回傳值。
(print若有印出東西時會回傳1打印失敗回傳0;可置於if函數做為邏輯判斷使用)

2檔案的副檔名必需為php,這樣伺服器才能知道內容PHP碼哦!

3php每個指令必需使分號「;」作為結尾。

PHP檔裡不要求得只能有php語法

<HTML>
<HEAD><TITLE>測試頁</TITLE><meta http-equiv=”Content-Type”content=”text/html; charset=UTF-8″>
</HEAD>
<BODY>
<?php
echo
“I’m here in the PHP!<br>
,and I’ll set a variable
\$ABC<br>”;
$ABC=”I’m fine.”;
?>
<table>
<tr>
<td>Are
you okey ?
</td>
<td>
<?= $ABC?>
</td>
</tr>
</table>
</BODY>
</HTML>

輸出:

I’m here in the PHP!
,and I’ll set a variable $ABC

Are
you okey ?
I’m
fine.

上例中可以發現到裡頭有許多html碼並不是用echo的方式打印出來的。當我們離開PHP時,此時頁面就如同在html檔裡一般,可以直接使用html碼;而php可以隨時打開它的結界,安插php碼在html語法當中。但有個例外:
如果php的完整語法進行到一半,此時離開了php進到html的語法中,php仍是會把中間段的html碼視為php完整語句中的一部分。例如:
<?php
if($GET[‘page’]==3) {  ?>

<span>目前在第三頁</span>
<?php  }  ?>
上例中的「<span>目前在第三頁</span>」仍屬於php中「if條件句」中一部分。
由於php碼會在其它語法(htmljs)中到處亂竄,因此用「<?php……?>」表示法較好,這樣能讓我們更容易找到它們。(也能避免伺服器不支援這樣的用法,雖然可以自行調整php.ini,但有些免費伺服器不提供這類的修改哦!)

認識echo

echo是要幫我們打印頁面的指令。換言之,echo所打印的內容才會成為網頁程式碼中的一部分,再配合該頁面中的其它html語法組合成一個完整且合乎語法的網頁頁面,再傳送給使用者。(當然,如果揍起來的語法不是合乎語法,就可能傳個亂碼網頁給使用者囉!)

echo可以打印「字串」、「變數」、「運算式」、「函數回傳值」…等;為了方便理解,我們可以把上述的引號內的元素都視為「字串」,例如:把「變數」視為一串字串,運算結果也視為一個字串。

字串必需放在引號「」或「」之間;不同的字串可以使用「.」把它們串起來成為較長的字串。例如:

$abc=”一個字串”;
echo  “這是”.$abc.”<br>3+5=”.(3+5);

會印出:
這是一個字串
3+5=8

其中,雙引號可以辨別字串中的「變數」(變數前後需要留一空格才能判讀,或者,使用大括號把變數包起)(3+5)是運算式,即使用了雙引號仍是無法判讀。而單引號中的內容全會被視為字串。
註:「.」與「+、–、*/%」同屬於運算子,「.」屬於字串的運算子。

由於網頁中常常會需要安插一小段php碼於html語法當中(通常是為了打印變數),此時就可以使用簡化版的打印方式。例如:

<?= $abc ?>等同於<?php echo  $abc ?>

上例中的$abc是個變數。以上列的操作方式即使句尾不加「;」也不算錯誤語法,結尾符號(?>)前可以省略句子的結尾。在css的語法中也允許這類的操作,例如屬性內容需要分號結尾,但在大括號”}”前的那一句可以省略,也可以省略最後一句的分號。
(
哎呀!說了那麼多就為了偷懶,+_+,培養好習慣,還是都加分號吧!)

關於註解

php中的註解方式有兩種:

一、行註解「//」:它會註解掉該行後面的資料。

二、區域註解「/*註解內容*/」:它會註解掉兩符號之間的內容。

合併上面兩種註解方式,可以巧妙地製作一個區塊註解開關「//*/」,以便於偵錯時使用。方法如下:
//*/  註記區一 目前資料並沒有被註記忽略,僅註記了本行
要被註記掉的程式碼…
要被註記掉的程式碼…
要被註記掉的程式碼…
要被註記掉的程式碼…
//*/   註記區一,目前資料並沒有被註記忽略,僅註記了本行

拿掉最前面的一個斜線後,才區者才會被註記忽略
/*/  註記區一 此時,整個註記區都將被忽略了
要被註記掉的程式碼…
要被註記掉的程式碼…
要被註記掉的程式碼…
要被註記掉的程式碼…
//*/   註記區一

關於變數

變數以「$」為開頭,內存在記憶體位址(位址是給電腦看的,是記憶體的機械代碼),不過,我們不需要知道位址是啥,只需要知道變數名稱即可;換言之,我們只需為變數命名,好讓電腦依此名稱去尋找記憶體位址。變數的值將會存放在這個記憶體位址後面。

此處提到三個的名詞「位址」、「變數名」、「變數值」,我們可以這樣理解,類似windows系統說G

變數名=捷徑;位址=檔案資料夾;變數值=檔案

當宣告「$abc=”這是一個字串”;」後,其中「$abc」是變數名;而「這是一個字串」是變數值,$abc內存放的位址是供伺服器電腦看的,電腦記的是位址而我們記的是變數名。

程式把「值」指定給「變數名」時,電腦會將該值存放到變數的位址後面,其後程式中使用到這個變數名時,電腦為幫忙到指定的記憶體位址中取得該值回傳。

註:把值設給變數名的動作稱為「賦值」,所使用的運算子是等號(=)
PHP
的變數可以存放的資料型態有:「數值」、「字串」、「數列(array)(或譯:數組)、「物件(object)(或譯:對象)、「資源(resource)」…等。

變數宣告 (或稱指定變數、賦值變數)

只要指定值(含空值)給帶有「$」符號的字串,即是宣告了變數。例如:「$ABC=””;」即賦值空字串給$ABC;若改為「$ABC=123;」稱為賦值123$ABC,也就是讓「$ABC」存放著數字「123」。

這些值將存放在記憶體位址後,會因程式運算而不斷地被改變,因此稱它為變數。賦值變數時也可以運算式,例如:

$ABC=($AA+$BB)/4;
(
即是運算後的結果賦值給變數$ABC
)

註:賦值變數是使用「=」,判斷兩邊資料是否相等時使用的是「==

關於傳值或傳址指定

前述的賦值方式都是以傳值的方式,也就利用「=」把其後面的值傳給該變數;例如:
$A=111;
$B=$A;  $C=$A;

此時三個變數都是存著111這個值,而這個值是分別存放在三個不同的位址裡。若想傳址必需改為這樣寫 $B=&$A(前面多個「&」符號),此時$A$B同址,此時三變數只用了兩個位址($C不同址)。由於$A$B同址,若值被修改了,兩個變數也會同步變化。

php中,函式內與函式外是不同的區塊,它們可以取相同的變數名稱,該變數將被給於不同的記憶體位址。不過,函式內看不到函式外的變數,反之亦然。

由於函式內外的變數不能互通,若想讓彼此資料交流的話,就需要使用到傳址,也就是把函式外的變數以傳址的方式傳給函數,如此一來兩個變數都是使用同一個位址,自然就有互通囉!參考下例:

$abc=’我是字串‘;
echo “在函數外先印一次
abc={$abc}<br>”;
kkk($abc);
echo “在函數外再印一次
abc={$abc}<br>”;
function kkk(&$a)
{//
傳值需求寫在函式中
$abc=”我是數字“;
echo “在函數內印abc={$abc}<br>”;
echo “在函數內印a={$a}<br>”;
$a=”不再是字串“;
echo “在函數內印改a={$a}<br>”;
}
輸出:
在函數外先印一次abc= 我是字串
在函數內印abc= 我是數字
在函數內印a= 我是字串
在函數內印改a= 不再是字串
在函數外再印一次abc= 不再是字串

註:用大括號包住變數才能讓雙引號認出它是變數,亦可用「.」來串連字串。

變更資料型態 (settypegettype)

當我們在宣告變數時其實已經指定了資料型態,例如:
$A=’abc’;
//此時,以指定變數$A為字串型態。
不過,有些時候仍是會有需要再把變數型態再明確化,例如:
$A=(int)($B/4);
//如此才能確保所賦的值個整數。

註:此方法,僅是傳給$A的值改了型態,$B仍是保留原本型態哦!

gettype($變數名稱):用來獲取變數型態的函式

gettype()通常是偵錯時使用,會使用echo指令來打印回傳值。不過,更常使用的是var_dump()函式,var_dump是專門用來打印變數的函式,不論是一般型態的變數或是陣列型的的變數都可以直接印出,不需再搭配echo指令。var_drum()可以同時放入許多變數,變數以逗號分隔,將來一同被打印到頁面中,可以一次性地看到所有變數的型態及其值。

設定變數型態的方式除了前面以(int)的方式指定外,還可以用

settyep($變數名稱,資料型態),以settype()函數來設定。

此設定會直接改變該變數的型態,不像(int)$ABC僅是回傳更變後的型態。
settype()
的回傳值是boolean(TRUEFALSE),即設定成功與否。

$abc=’我是字串‘;
$arr=array(a,b,c,array(1,2,3,5),e,f,);
$ABC=”123″;
echo gettype($arr).”<br>”;
echo gettype($abc).”<br>”;
echo 
gettype($ABC).”<br>”;
settype($ABC,int);
settype($abc,int);
echo
gettype($ABC).”<br>”;
echo 
gettype($abc).”<br>”;
echo $abc;
echo $ABC;
輸出結果: 
array
string
string
integer
integer
0
123
說明:
$abc的值是字串,也將成功被轉成數字型態了;
不過,它的值卻變成0了;
而字串型態的數值,可以正確地轉為數字型態!

若只想取出特定型態的資料而不打算更變原變數型態時,可使用下列函數:

intval()
floatval()
Strval()
boolval()
取為整數
取為浮點數
取為字串
取為布林型態
settype是直接把變數轉換型態,而intval($ABC)只是取值,效果同(int)$ABC
當無法把字串轉為數字時,則回傳0;
特殊:可變變數 (以變數值去命名變數~~真不知道怎麼用它=_=|||)
$abc=’我是字串‘;
$ABC=”123″;
$K=’abc’;
$D=’ABC’;
echo 
$$K.”<br>”;
echo 
$$D.”<br>”;
輸出:
我是字串
123

 

註:PHP的變數與常量都有區分大小寫 (函數名則不分大小寫)
變數名稱必需以英文字母或底線( _)做為開頭。

附上變數型態表以便查閱

資料型態
識別字
說明
整數

integerint

-2147483647 ~
+2147483647

雙精確數

doublefloatreal

雙精確數、浮點數、實數

字串

string

必須用 “ “ 包含

布林值

Boolean

真(T/1)、假(F/0

陣列

array

存放整組資料

物件

object

 

資源

resource

用來保存對外部資料的引用

空值

NULL

未設資料的變數值

邏輯式判斷型態的函數(全都回傳boolen)

is_int()

is_float()

is_array()

is_null()

is_resource()

is_bool()

is_string()

 

resource(資源),指:CSSJavascript、外部連結、資料庫…之類的資源

isset($變數):判斷變數是否存在的函數,回傳bool值。

unset($變數):重設變數的函數,即將變數值改為NULL

關於isset()函式的回傳值,NULL與空字串的回傳結果並不同唷!
對於存放空字串的變數,isset的回傳值是TRUE,因此,想讓它判斷為FALSE的話需使用unset函式,或者,自行將變數賦值為NULL

好用的函式var_dump($變數)print_r($變數)

var_dump()可以幫我們印出任何的變數,除了印出資料內容外也一併印資料型態、資料長度、內容筆數、所在的行…等資料,是個偵錯的好幫手。當你對某變數值或型態不確定時,或是對於表單傳來的資料不確定時,都可以使用它來幫忙。

print_r()是專面用來打印array的函式,不過它沒有排版,會讓畫面感覺很亂,只好自己印<pre>囉!例:
echo “<pre>”.print_r($_POST,true). “</pre>”;exit;
在文件開始處寫入這一行,即可知道表單傳來的內容。
註:exit將中止程式,可視需要使用。不想使用時可先註記掉此行

套裝軟體Ampps中的php預設會幫var_dump()所列印的內容前後加上<pre>標籤,並且套用專屬的css樣式讓字串變色以利於閱讀,也讓陣列以樹狀型態印出。
Xampp
似乎沒有幫忙加上<pre>標籤,因為若想讓var_dump()的輸出內容排版好看一點,就自己加上<pre>吧!例:
echo “<pre>”;var_dump($aa,$bb,$cc);
echo
“</pre>”;

若是覺得這樣要寫成三句很麻煩,就自行把它置作成自定函式吧!

定界符(<<<) 真是個神奇的玩意兒

$ABC=”我是變數“;
$B=<<<AAA
即使內容有都會被秀出來;$ABC(不需前後留空格);
AAA可以任意命名,
結尾的AAA需左緊靠行首。
AAA;//記得這兒要緊靠行首,補上分號
echo “<pre>”.$B.”</pre>”;

輸出:

即使內容有都會被秀出來;
我是變數(不需前後留空格);AAA可以任意命名,
結尾的AAA需左緊靠行首。

 

定界符可以把一大堆內容(含換行符號、跳脫字元、變數…)
全都不失真地傳給變數$B,很適合用來存放「大型且有排版的文字」

上例定界符中說到,其內容可以包含特殊字串並且如實印出,一般情況下,引號「」是用來包含字串的字元,如果字串中想要印出引號時就必需使用跳脫字元「\”」,不然程式會產生誤判。

以下即是所謂的特殊字串

跳脫字元
說明
跳脫字元
說明
\’
顯示「」符號
\r
Return
\”
顯示「」符號
\t
Tab
\b
Backspace
\$
顯示「$」符號
\n
換行符號
\\
顯示「\」符號

以上字元有的是指令用的字元,因此必需跳脫;而有些功能型的字元並無法用文字表示時,也採用跳脫字元表示。不過,並不表示使用該跳脫字元就真有其功能。
例如:\t並不會有Tab鍵的功能,\n也不見得會換行,畢竟瀏覽器是依<html>語法來換行的。可是,在配合javascript語法時,有時就能發揮功能囉!

定義常數(或譯:常量)

define(“常數名”,常數值)

直接從例子來講:define(“PI”,3.1415926),此後,「PI」字串就變成特殊符號了,PI代表3.1415926這個數值。

常數一旦被定義後,就無法再更改或取消囉!

使用define()函式來定義常數時,常數名必需以雙引號包含。
常數值的型態可為:stringintfloatboolean 四種!

檢查字串是否為常數

defined(“字串”)

defined(‘FILE_READ_MODE’)  OR define(‘FILE_READ_MODE’,0644);

中間的「OR()」是邏輯判斷的短路用法,若前面為真,則會忽略其後面內容;因此,這段的法語法的思路是:先以defined()判斷該字串是否為常數,若是(回傳true)則不再另行定義,若不是則由我們來定義該常數的值。

 

系統常量

輸出:

printf(“M_PI: %s <br>”, M_PI);

printf(“PHP_OS: %s <br>”,PHP_OS);

printf(“PHP_VERSION: %s <br>”, PHP_VERSION);

M_PI: 3.1415926535898

PHP_OS: WINNT

PHP_VERSION: 5.6.31

註:M_PI=圓周率近似值;PHP_OS=作業系統;PHP_VERSION=PHP的版本

魔術常量(此常量非定值,不同環境會變成不同的值)

寫個小程式打印一下魔術常量

輸出:

printf(“LINE: %d <br>”, __LINE__);

printf(“FILE: %s <br>”, __FILE__);

printf(“FUNCTION: %s <br>”, __FUNCTION__);

printf(“CLASS: %s <br>”, __CLASS__);

printf(“METHOD: %s <br>”, __METHOD__);

LINE: 28

FILE: C:\www\test\note.php

FUNCTION:

CLASS:

METHOD:

註:後三個打印沒有回傳結果,是因為我並沒有把它放在所屬的條件下(函數、類…)

__LINE__

目前指令在第幾行

__FILE__

目前檔案在伺服器的實體絕對位址

__FUNCTION__

指令所在的的函數名

__CLASS__

指令所在的的類(class)

__METHOD__

指令所在的的方法名(類裡的函數)

註:魔術常量在英文字母的前後都是兩個底線「__

 

php中除了有系統常數、魔術常數外,也預設了大量的變數,其中有一些變數所儲存的資料非常實用,在設計上可以直接取來使用。

 

以下表列一些實用的預設變數,這些變數都是全域變數:

預設變數

說明

$_SERVER

存放伺服器及目前程式的環境資訊的陣列

陣列索引

內容資訊

PHP_SELF

目前網頁的虛擬路徑

SERVER_NAME

目前網頁的伺服器名稱

SERVER_PORTOCOL

通訊協定名稱及版本,例:
HTTP/1.0

REQUEST_METHOD

目前頁面請求變數的方法,例:
GET
POST

DOCUMENT_ROOT

頁面所在網站的根目錄

HTTP_HOST

頁面所在的伺服器位址

REMOTE_ADDR

目前網頁客戶端的IP

REMOTE_PORT

目前網頁客戶端的連接埠

SCRITP_FILENAME

目前頁面的絕對路徑

SERVER_PORT

目前網頁伺服器的連接埠

其實這個變數不只這些內容,以print_r實際印看看即會發現它有
37
個元素,隨著版本及網頁需求的改變也許將來還會更多。

$_EVN

環境變數,存放PHP執行環境資訊的陣列

$_GET

來源頁面若以網址列傳值,該值會暫存在這個陣列中

$_POST

來源頁面的表單以POST傳值,該值會暫存在這個陣列中

$_SESSION

設置SESSION時,相關資料都將存放在這個陣列中

$_COOKIE

從用戶端所取得的COOKIE資訊,都將存放在這個陣列中

$_FILES

POST上傳檔後,上傳資料的相關資訊存放在這個陣列中

$_REQUEST

關於GETPOSTCOOKIEFILES的相關資訊,
這個陣列也都留有一份。

註:常用的$_POST變數內容會在送出網頁時即清空;而$_GET陣列中的內容是以網址列內容而定,若網址一直不變,即使清空了又會馬上再次獲得該值。

正規表達式

社群:網頁設計
作者:宥晰

正規表達式提供一種泛用的字串樣式,它是以一組特定字元符號去描述字串樣式的規則。它讓設計師可以先製作範本(pattern)再以範本去比對字串,比對後再視需要對該字串進行操作。常見的操作有:
「格式檢查」、「字串取代」、「字串拆解」

範本的形式:/正規表達式/[修飾條件]

其中,「/」為分隔符號,將範本置於兩個分隔符號之間以作區隔。右邊分隔符號後方可加註修飾條件(modifier選用),例如:
/\w{3}/i  其後方加了「i」表示不區分大小寫。(比對三個字母或數字)

比對時,將一一取出字串中的每個字元去比對範本,但是什麼情況稱為「匹配」(比對成功),跟誰去匹配呢?匹配的對象稱為字元集合。

範本需要有個方式來表達「字元集合」,換言之,被比對的字元必需符合「字元集合」內的元素才算一次成功的比對。

字元集

字元集的呈現方式是以中括號「[ ]」包含,被拿進來比對的字元若與中括號內的某個字元相同,即算匹配(比對成功)。例:
[abc123],意指:只有a、b、c、1、2、3這六個字元可以比對成功。

也可以使用「否定」的方式呈現字元集,當我們在中括號內的開頭處加上「^」符號時即表示為否定,例:
[^123],意指:非1、2、3的字元都能匹配。

註:「^」這個符號在正規表示式中有兩種完全不一樣用途,別搞混囉!
在字元集開頭處表示否定();在字元集外表示檢查字串開頭處。
(若在中括號裡卻不放在字元集開頭處,則將「^」這符號視為字元集中的一個字元。)

連續性的字元可以用「-」(dash)符號來簡化它。例如:[a-zA-Z.-],意指:所有的大小寫英文字母並外帶「.-」兩個字元。
註:單一字元的字元集,可省略中括號。

一些常用的字元集,PHP提供一些簡化的表達方式:

[:alpha:] 所有字母,等於 [a-zA-Z]
[:lower:] 所有小寫字母,等於 [a-z]
[:upper:] 所有大寫字母,等於 [A-Z]
[:alnum:] 所有字母和數字,等於 [a-zA-Z0-9]
[:digit:] 僅數字,等於 [0-9]
[:xdigit:] 僅16進位的字元,等於 [0-9a-fA-F]
[:space:] 所有空白字元,等於 [\n\t\r\x0b]
[:punct:] 所有半形標點符號,同[.,”‘?!;:],(Punctuation symbols)
[:blank:] space and TAB characters only,同 [ \t] (空格與Tab)
[:graph:] 所有的可列印字元,等價於:[^  /t/n/r/f/v]
[:print:] 所有的可列印字元含空格,等價於:[^/t/n/r/f/v]
[:cntrl:] 所有ASCII 0到31之間的控制符

註:簡化版的字元集,使用時(在範本中)仍需再加中括號,例:/[[:lower:]]/

table,th,td{border:1px solid gray;}
\s 表示空白字元,包含\t、\v…等。
\S 表示非空白字元
\d 表示所有數字,等於 [0-9]
\D 表示數字以外的字元,等於 [^0-9]
\w 表示所有字母和數字及底線_,等於 [_a-zA-Z0-9]
\W 任何\w以外的字元。[^_a-zA-Z0-9]
. 表示為任意單一字元。( “.” 為英文句號dot).

重複比對次數(不指定時,預設為{1})

字元集提供範本比對的對象,我們可以進以步地要求匹配的次數。緊接在字元集後方以大括號指定匹配的次數。方式如下:

        [字元集]{次數}  或  [字元集]{最小值,最大值}

上例左式,需剛好符合指定次數才算匹配;上例右式是給予一個次數區間,凡符合區間內的次數都算是匹配成功。右式中的最大值與最小值可以省略(仍需保留逗號),其意義為:(設n為整數)

        { ,n} :表示0到n範圍;{ n,} :表示n以上的次數。

其它指定重複次數的符號:(一樣置於字元集合後方)

? 重複0或1次,等同於 {0,1}
* 重複0或多次,等同於{0,}
+ 重複1或多次,等同於{1,}

前面提到的「.」(dot)這個符號,它包含了字元集及次數,代表為任意字元1次。相當於是[^\n]{1}。若需要比對「.」這個符號時,需使用轉義符號「\」,即以「\.」來表示「.」這個符號。「.」的任意字元並不包含換行符號(\n),除非加上/s修飾條件。

註:在中括號(字元集)裡不需使用轉義符,單獨使用時才需轉義,例:

        比對URL:/http://(/[\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?/

常用的跳脫字元(用於子表達式內,不使用於字元集([ ])中)

table,th,td{border-collapse:collapse; border:1px solid #000;font-size:12px;text-align:center} td{width:50px}
原字元 . + * \ Enter Tab Backspace Esc
跳脫字元 \. \+ \* \\ \n \t \r \e

註:「()[]{}及|(OR)」這些俱表達式功能的字元也需要使用轉義符號。

定界符號

「^」與「$」這兩個符號為定界符號,「^」只會檢查字串的開頭處,「$」只會檢查字串的結尾處。這兩個符號都置於字元集外,^緊接在左分隔符號(/)後方,將匹配其後面的字元集;$需置於右分隔符號前,將匹配前面的字元集。例如:

        /^\d{3}[a-z]+$/  表示字串以3個數開頭並以英文結尾才算匹配

註:$置於範本中間時無意義,而^在字元集中是否定的意思。

子範本(sub  pattern 或稱子表達式)

如果我們把兩個分隔符號(/)間的表達式稱為主範本,在主範本裡我們還可以再以小括號「()」分隔出子範本;換言之,我們可以視為多個子範本組成了一個主範本。

php設有暫存區來存放所有的子範本,我用可以利用\\n或$n來調用第n個子範本所配對成功的字串資料。正是因為可以調用這些暫存資料才讓表達式的實用性顯得更強大了。

當有設置子範本時,程式會依序由左而右將子範本存放在\\1~\\99(或$1~$99)的暫存區中。例如:

        /^([A-z])([1-2])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])$/

上例中刻意將身分證號拆分成10個子範本,於是我們可以在\\1~\\10中取得個身分證號的每個字元。而\\0(或$0)也是個暫存區,所存放是主範本所取得的完整字串。(註:「\\」包含了轉義符號)

我們可以取用暫存區的字串作為preg_replace()的取代內容,也可以拿暫存區的內容來調整字元集。要注意的是,拿暫存區內容來調整字元集時需考慮先後次序,也就是說,擺在後面的子範本可以參考前面子範本所取得的內容來調整自己的字元集。

不僅是php的正規表示式有這樣的功能,其實HTML5的表單驗證也支援這樣的功能,參考下例:

<input type=’text’ name=num4′ size=’5′ maxlength=’4′ required
pattern=’ ^(\d)((?!\1)[\d])((?!\1|\2)[\d])((?!\1|\2|\3)[\d])$’ />

上例中的範本(pattern)可以匹配四個相異的數字。後面的子範本參考了前面範本所取得的數字,並要求自己的字元集中不包含前面所取得的數字。這個原本需要動用到javascript的功能,目前HTML5已經幫我們做到了,很多瀏覽器也都支援這個功能。

上例中有使用到「|」這個符號,它的意義即是「或(OR)」的意思。「|」用於子範本中但不用於字元集「[ ]」內。在子範本中使用「|」,表示「擇一」的意思,例:/AA\.(txt|doc)/表示將匹配AA.txt或AA.doc。

上例中還使用到「?!」這個特殊功能,此功能稱為「向前查詢」。

向前查詢及非補獲組  (“?:”、”?=”、”?!” 的應用)

前面說道,每個子範本所取得的子字串都會被存放到暫存區中,我們也可以設定不讓該子字串被放到暫存區裡,即是「非補獲組」。

在小括號中的開頭處加上「?:」時,這個子範本將不被存放到暫存區中,我們將無法使用$n來取得該子範本的內容。除了「?:」不會被存到暫存區中,小括號裡若有「?=」或「?!」的話,也不會存到暫存區。

而「?=」與「?!」是對子字串的開頭字元做了限制,「?=」表示為「取用」(正向查詢)而「?!」表示為「不取用」(負向查詢),例如:

        (?=e)(\w*) 表示該子字串需是以「e」開頭的字母或數字;
        (?!\1)(\d) 表示這個子字串需不含第一暫存區的字元且必需是數字

註:可以把(?!\1)(\d)這兩個小括號視為一個子範本,因為前面的子範本並不會被存到暫存區裡,而取得的字元仍需符合後面的子範本要求。

操作符號的優先順序

正規表示式有許多操作的符號,確定優先順序也是非常重要:

轉義符號 圓方括號
萬用字元
限次符號 定界符
修飾符
\ ()、[]. *?+{m,n} ^、$、/修飾 |

註:轉義符號包含\b、\w這類的字元集或單字定界的功能

其它較少使用的控制符號

\xNN NN代表兩個16進位的字元。藉此表達在字元集中表達ASCII 字元碼,通過 ASCII 值指定範圍。
\uN N表示四個16進制的字元。可藉此於字元集中表達Unicode 字元
\b 於表達式中,表示單字的邊界。(屬於單字的定界符)
\B 與\b相反,表示非單字邊界。例::/\Bapt/ 不能匹配abtitude
\w 表示所有字母和數字及底線_,等於 [_a-zA-Z0-9]
\W 任何\w以外的字元。[^_a-zA-Z0-9]
\cX X必需為[a-zA-Z]中的字元,不然\c會被視為”c”這個字元。
此為控制字元,代表”control-X”。
javascript做前台操作時才可能會用得到它。php是在伺服器端做字串操作,用不到這個功能。
\e 匹配escepe鍵。同上,僅前台操作才可能用得上。

註:\b在字元集內時[\b]代表退格(同\u0008),此字元打印不出來,一般不太可能會在字元集中使用它。由於符號同於單字定界符,僅需知悉即可。

關於修飾符號(modifier)

在PHP中修飾符有:
「i、m、s、x、e、A、D、S、U、X、J、u」共12種

i 不區分英文字母的大小寫。
m 有換行符號時(\n)才有作用。每一行都會被^、$比對字串頭尾。
若沒設定m時,整個字串只會有一組頭尾。(若設了m則會忽略D)
s 讓「.(dot)」這個符號包含換行符號(\n)。預設”.”不包含\n。
注意,[^a](除了a)這類的否定字元集其實是包含換行符號的。
x 忽略空白字元。但字元集內或含轉義符的不會被忽略。
“#”這個附註字元,在其後且在換行符號前的內容也會被忽略。 註:取到暫存區的子字串也不會含有空白字元。
A 強迫定錨(anchor)於字串開頭處。子字串也需從字串開頭處比對。
D 設定後,字尾界符($)會完全比對字串的最後一字元包含(\n) 一般情況下,會忽略換行字元(即比對到\n的前一字元)。 (不可以m同使使用,若設了m則會忽略D)
S (沒使用過它)。就官網的說法是,設定了此修飾後,會額外對此範本加強分析以提昇分析速度。對於頻繁使用的範本值得附加它。
U 切換貪婪模式。預設是貪婪模式,但若設了U後會先以非貪婪模式開始,值到遇上”?”後才轉為貪婪模式。
所謂貪婪模式,即是在比對過程中即使比對到完全符合的字串也不會停止比對,它會比對整個的字串,取出較長且符合的字串。
若想在預設貪婪模式中轉為非貪婪模式的話,僅需在範本(pattern)裡加個”?”即可。例如:比對任意字串時,把 /(.*)/ 改為 /(.*?)/

註:e僅在preg_replace()使用,會於5.5版出現提醒,並於7.0版移除。
e的修飾會把preg_replace()的取代字串視為php的程式碼求值後再取代。並且會自動為單引號(‘)雙引號(“)倒斜線(\)及NULL加上跳脫符號”\”。

X 讓無效的「倒斜線功能」產生錯訊息。例如:\p無功能,於是就產生錯誤訊息。藉此保留此組合以備未來擴充之用。
預設情況下,若沒設置/X,\p會視為”p”這個字元。
u 將範本及目標字串都視為UTF-8的字碼。註:php5.3.4版後,UTF-8的第五、第六字節的字符會被視為無效字元。(無效字元無法匹配)

J
7.2.0版後才可使用的修飾符號。用於改變內部正規表達式的設定,允許子範本有重複的名稱。(實在不曉得這功能怎麼用?)

註:修飾符號置於右分隔符號後,可以同時置放多種修飾,例:/範本/imU

PHP中關於正規表示式的函式

int preg_march( 範本, 目標字串, [&結果陣列], [flag=-1], [offset=0] )
這是字串檢查中最常用的比對函式。雖然它最多可設5個參數,不過,一般只會使用三個參數。範本即是正規表達式,以範本去比對目標字串,若有相符的部分就存入第三參數陣列中。(若僅判斷是否有符合則不需設置第三參數)
回傳值為比對成功的次數,不過一旦成功此函數將停止比對,換言之,此函數只會回傳0或1。若發生錯誤時才會回傳false。 flag 預設值為-1,它有以下兩種設定: PREG_OFFSET_CAPTURE 結果陣列附帶子字串的啟始位置 將把「結果陣列」改為二維陣列,陣列元素都是含2個元素的陣列,兩元素的內容為[0]=>取獲的子字串,[1]=>此子字串的啟始位置。 PREG_UNMATCHED_AS_NULL 讓未匹配以NULL呈現。 原本原匹配會存放空字串,改為存放NULL。(僅影響結果陣列) offset為忽略字元數(以byte計算),換言之,即是設定字串比對的起始位置,若被忽略了三個字元,那麼第四個字元視為字首(可與”^”匹配)

註:要比對字串到底應改用preg_match_all()

mixed  preg_replace( 範本, 取代式, 目標, [limit=-1], [&$count] )
函式是以範本(pattern)去選定目標的特定範圍,再以取式去修改它。 範本比對目標時所取得的子字串將依序存放在\\1~\\99區段中,取代式可以利用「\\區段號」或「$1~$99」來提取該區段的字串並組成新字串。
其中,\\0是存放比對成功的完整字串。 limit:設定範本所能產生的子字串上限,預設為-1(不設限) count:計數器,計算取代動作共進行了幾次。(需為變數,將傳址入函式) 回傳值依目標的型態而定,若目標為字串則函式回傳字串,若目標為陣列則函式回傳陣列。若發生錯誤則回傳NULL 前三個參數既可以是字串也可以是陣列,不全為字串時的處理方式如下:
1
、若取代式為字串而範本為陣列時,所有的範本皆依此取式式來處理。
2
、若取代式與範本都是陣列時,將依相同索引的取代式去置換同索引的範本所獲取的字串範圍。若範本的元素量多於取代式時,多出來的範本取得字串都將被置換為空字串。

修飾符/e即將停用,官方建議改以preg_replace_callback()取代

常遇到的無效修飾錯誤(/d)

錯誤範例
$str = preg_replace(‘/<div> </div>/i’, ”, $str);
正確寫法
$str = preg_replace(‘/<div> <\/div>/i’, ”, $str);
即</div>的收尾的斜線必需要跳脫,不然會誤判為範本的分隔符號。

preg_replace_callback( 範本, callback, 目標, [limit=-1], [&$count] )
功能與preg_replace()極為相同。僅取代式改為callback(是個函式)。 此處的callback可以自定函式或無名函式,此函式必需有回傳值。 preg_replace_callback()會將範本所取得的子字串製成陣列,並將此陣列作為callback()的參數;callback()可利用參數的資料來製作取代字串回傳。
註:被帶入callback()中的字串都會自動轉義為跳脫字元。範本設定很容易在此失誤而匹配不到任何字串。

超級難,上php.net看例子吧!一堆神人對此函式的用法真是絕妙!!

無名函式(Anonymous functions)的用法可參考下例:(取代為下一年)

$text = “April fools day is 04/01/2002\n”;
echo  preg_replace_callback( “/(\d{2}/\d{2}/)(\d{4})/”,
function($matches) { return $matches[1].($matches[2]+1); }
,$text );  //輸出:April fools day is 04/01/2003\n

array  preg_split( 範本, 目標字串, [limit=-1], [flags=0] )
以範本拆分目標字串為一個陣列。範本僅以字串型態表示。
回傳值是個陣列,內容元素為以依範本所收集到的所有子字串。 limit:設定範本所能產生的子字串上限,預設為-1(不設限) flags:有以下三種設定。 PREG_SPLIT_NO_EMPTY 非空字串才回傳。 PREG_SPLIT_DELIM_CAPTURE 空字串也會回傳。 PREG_SPLIT_OFFSET_CAPTURE 回傳陣列的元素值,都是內含兩元素的陣列:
[0]=>]字串,[1]=>該字串的起始位置。