Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Regular Expression
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
關於正規表示式的一點筆記
05 MAY 2011 on PHP, Work, Regular Expression, 正規表示式
我發現我很久沒有寫 PHP 的筆記了,不過因為我本來就不太會寫 PHP,所以文章很少也是很合理的(挺)。這次要筆記的東西是正規表示式,其實網路上文章非常多,我首推這篇:Regular Expression (RegExp) in JavaScript

疑?怎麼是 Javascript!?哎呀,沒關係啦,其實正規表示式大家都差不多嘛(喂)。但是呢,我這裡筆記的東西請不要直接搬去給 Javascript 用,會出人命的。首先,我要講得東西這邊全部都有:

PCRE regex syntax

所以如果英文不錯的人可以直接看官方說明就好。我這裡只是因為英文很爛所以筆記一下而已(無責)。比較基礎就不再贅述了,去問 Google 大神應該可以找到一大堆,倒是,這一篇官方說明可以筆記一下,有一些跳脫的字元可以留意一下,免得誤觸地雷。

Escape sequences

至於 Internal option setting 也請記得,不要誤用。請注意 PCRE_MULTILINE(/^(.*)$/m)的設定,他會讓你的定位結果(使用 ^ 與 $ 時)與其他的設定不同。而,這個設定也可以在 Subpatterns 中使用,使用的方法大概是這樣:(?i: 或是 (?m<= 爾等。

接著來提一下 Subpatterns 的作法。在正規表示式中,我們可以依照提取出來的結果,更準確的把我們想要的部份個切割開來。這種時候 Subpatterns 就異常的好用。首先先說明一下我們有哪些工具可用:

( ) 最常見的括號,代表將內容做一個記憶群組動作。
(?: ) 與括號作用相同,不同的是,這個群組是不會被記憶的。
(?| ) 當群組使用多選時,可以避免沒有選中結果,但卻產生空的群組(該群組還會被記憶)。
(?<name> ) 群組命名,一般正規輸出都是單純陣列,這個命名會是陣列鍵值。
另外還有比較特殊的用法,稱為右(左)合,右(左)不合的形式,可搭配條件比對使用:

(?= 左合樣式
(?<= 右合樣式
(?! 左不合樣式
(?<! 右不合樣式
另外也是特殊用法之一,單次比對(Once-only subpattern):

`(?> 顧名思義就是,我只比對一次。
還有條件式比對(Conditional subpattern),請搭配左(右)合(不合)樣使用:

`(?(condition)yes-pattern) 照字面上的意思,就不用多做解釋了吧。
`(?(condition)yes-pattern|no-pattern) 同上,只是多了個 no-pattern 而已(喂
然後,既然有群組(不管是否有記憶動作),就能夠拿出來參考(Back references):

\1 常見用法,將第一個群組拿出來用。
\g1, \g1, \g{1}, \g{-1} 取出特定群組用法,用大括號有一個特別的地方就是,可以避免一些問題*。
(?P=name) 遇到有命名的群組,這樣可以把該群組拿出來用。
舉一個例子,我用顏色區隔應該會比較好理解一點(有嗎?):

"/(?:(?P(?|_t|_f|_text|_textf))((?P(?|'|\")))(?P
*)?/i"
這是我用來掃描原始碼,當其中有 _t('xxxxx') 或是 _text("xxxxx") 出現時,把 _t 這類的程式名稱命名為 tag,把 ' 或是 " 命名為 quote,然後把程式包的內容命名為 content,其中 content 的內容是非第一記憶群組的所有文字。抓出來就是我要的結果嗎?

假設變數是這樣:

$a = '_t("123") _f(\'456\') _text(\'789 "12345" 6789\')';
其實結果並不如預期,無論在單行或是多行處理時,最後一個條件會符合這種情況:

_t('123
_f('456
_text('789 // 這裡出現斷尾了!