Let results of preg_match be an associative array
在 Regular Expression (REGEX) 的語法中,有一種方式可以讓我們將 subpatterns 的內容存放在一個數值索引陣列,而以 $1, $2, $3, ... (或 \1, \2, \3, ...) 的敘述方式取用。雖然這已經很方便了,但仍然有缺點,就是比對結果不易理解,時日一久,很容易忘記 $1, $2,... 各是代表什麼意思。所以 PHP 在 4.3.3 版之後增加了一個新語法,可以指派名稱給 subpattern ,這個語法格式是: (?P<name>pattern) 。如此一來就可以將 subpatterns 的內容存放在一個關聯陣列 (associative array) 中,可以鍵值取用,提高程式可讀性。
對於 Regular expression 基本語法,我假設讀者已經熟悉了,不做細部說明。
Example of preg_match()
以 HTML 中的 input 標籤為例,將 input 標籤中的 name 和 value 屬性的值比對出來,並利用為 subpattern 命名的語法,令 preg_match() 產生一個有鍵值 'name' 和 'value' 的關聯陣列。
<?php $s = <<<PAGE <input class="textBox" type="text" name="userName" value="abc" /> PAGE; preg_match('/<input[^>]+name="(?P<name>[^"]+)"[^>]+value="(?P<value>[^"]*)"[^>]*>/', $s, $field); print_r($field); echo $field['name'], ' = ', $field['value']; ?>
Example of preg_match_all()
以 HTML 的表單元素為例,將其中 input 和 textarea 元素的 name 與 value 屬性的值分別比對出來,最後利用陣列函數,將結果合併成為一個對應表單內容之 key => value 的關聯陣列。
<?php $loadPage = <<<PAGE <form> <label>Name: <input class="textBox" type="text" name="userName" value="abc" /> </label><br/> <labe>Phone: <input type="text" name="userPhone" value="123456" readonly="readonly"/> </label><br/> <label>Address: <input name="userAddress" type="text" value="ROC"/> </label><br/> <text_area name="Note">hello world. Today is monday.</text_area> </form> PAGE; // 1. fetch field putting in input preg_match_all('/<input[^>]+name="(?P<name>[^"]+)"[^>]+value="(?P<value>[^"]*)"[^>]*>/', $loadPage, $matches1); print_r($matches1); // 2. fetch field putting in textarea preg_match_all('/<(textarea)[^>]+name="(?P<name>[^"]+)"[^>]*>(?P<value>.*)<\/\1>/', $loadPage, $matches2); print_r($matches2); $fields = array_combine( array_merge($matches1['name'], $matches2['name']), array_merge($matches1['value'], $matches2['value']) ); print_r($fields); foreach ($fields as $k => $v) { echo 'Value of field ', $k, ' is ', $v, ".\n"; } ?>
我常常將這種技巧用在 JSP 或 ASP.Net 產生的網頁內容上,那些網頁常常使用 WebUI 控制項來顯示網頁內容,因此網頁有大量表單元素 (input, textarea, hidden, select, ...) ,這些元素都包含 'name' 和 'value' 屬性。要從中取出這些 name 和 value 的內容,正規做法應該是用 PHP 的 DOM functions ,但我覺得太麻煩,而效能也是一個考量因素,因此我通常選擇使用 PCRE functions 將那些內容「比對」出來,利用指派名稱給 subpattern 的擴充語法,就更敏捷了。