進階Regex專題

來源:互聯網
上載者:User

說起Regex,可以一直上溯至對人類神經系統如何工作的早期研究。Warren McCulloch和Walter Pitts這兩位神經生理學家研究出一種數學方式來描述這些神經網路。

1956
年,一位叫Stephen
Kleene的美國數學家在McCulloch和Pitts早期工作的基礎上,發表了一篇標題為“神經網事件的標記法”的論文,引入了Regex的概念。
Regex就是用來描述他稱為“正則集的代數”的運算式,因此採用“Regex”這個術語。

隨後,發現可以將這一工作應用於使用Ken Thompson的計算搜尋演算法的一些早期研究,Ken Thompson是Unix的主要發明人。Regex的第一個實用應用程式就是Unix中的qed編輯器。

這個專題主要是為了提高大家對Regex的認識和進階的使用。

1 使用Regex來檢測HTML是否關閉

function check_html($html) {
    preg_match_all("/<([a-zA-Z0-9]+)//s*[^///>]*>/",$html,$start_tags);
    preg_match_all("/<///([a-zA-Z0-9]+)>/", $html, $end_tags);
    if(count($start_tags[1]) != count($end_tags[1])) return false;
    for($i = 0; $i < count($start_tags[1]); $i++) {
        if(!in_array($start_tags[1][$i], $end_tags[1])) return false;
    }
    return true;
}

解釋:

/<
([a-zA-Z0-9]+)//s*[^///>]*>/這個模式是用來匹配HTML的標記(如:<head>、<
div>、<div
id="main">等等,但是除了<br/>這種)的,並且在$start_tags保持著標籤的名字(如:head、div等)。
而/<///([a-zA-Z0-9]+)>/這個模式是用來匹配閉合的HTML標記(如:</head>,
</div>等)的。並且在$end_tags中保持這閉合的標籤名。然後我們用count($start_tags[1]) !=
count($end_tags[1])這個條件陳述式來判斷開始的標記跟閉合的標記是否相等,不相等就說明沒閉合。最後用in_array($
start_tags[1][$i], $end_tags[1])來判斷開始標跟閉合的標記是否相等。至此,我們就完成了HTML的匹配了!

2 匹配E-mail格式

function check_email($email) {
       
if(preg_match("/^[/w/d!#$%&'*+-//=?^`{|}~]+(/.[/w/d!#$%&'*+-//=?^`{|}~]+)*@([a-z/d][-a-z/d]*[a-z/d]/.)+[a-z][-a-z/d]*[a-z]$/",
$eamil)) return true;
        return false;
}

解釋:

不要被
/^[/w/d!#$%&'*+-//=?^`{|}~]+(/.[/w/d!#$%&'*+-//=?^`{|}~]+)*@([a-z
/d][-a-z/d]*[a-z/d]/.)+[a-z][-a-z/d]*[a-z]$/這條模式給嚇跑了,其實也很簡單的。前部分[/w/d!#$
%&'*+-//=?^`{|}~]+(/.[/w/d!#$%&'*+-//=?^`{|}~]+)*只是匹配符合RFC-2882標
準的E-mail地址允許出現的字元,就是英文字母,數字跟一些符號,有興趣可以查詢RFC-2882手冊,而([a-z/d][-a-z/d]*[a-
z/d]/.)+就是匹配HOST的。最後[a-z][-a-z/d]*[a-z]就是匹配頂級網域名稱的(如:.com、.org)。

3 非貪心模式

有時候使用Regex的時候,你會發現有以下的問題:

preg_match('/".*"/', 'Tony say:"hello", Jack say: "Hi"', $matches);
print_r($matches);

很驚奇的你會發現匹配的是這樣的內容"hello", Jack say: "Hi",而不是"hello"和"Hi"。這就是貪心匹配引起的。在貪心匹配中,Regex會儘可能的匹配最多的字元,所以出現了第一種情況,但是我們想要的是第二種情況,那我們要怎麼做呢?

我們可以使用非貪心匹配,將剛才的模式改為/".*?"/這樣就可以看見我們想要的結果了。*?這個就是非貪心匹配模式。還有另外一種就是+?。
 *?:前面的字元可以出現任意多次,但是遇到*?後的一個字元即停止匹配。
 +?:前面的字元可以出現一次或者多次,但是遇到+?後的一個字元即停止匹配。

4 檢測一個使用者密碼是否安全

function is_good_pw($pw) {
    if(preg_match('/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,16}/', $pw)) {
        return true;
    }
    return false;
}

解釋:


本例中,我們使用了/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,16}/模式來匹配我們的密碼。在這個模式中,我們使
用了Regex中的前瞻模式(?=)。(?=.*[0-9])這個是匹配密碼中有數字,而(?=.*[a-z])是匹配密碼中有小寫字母,最後(?=.*
[A-Z])就是匹配密碼中有大寫字母。而.{8,16}這個就是匹配密碼是由8至16個字元組成的。那麼我們的密碼就需要有數字,大寫字母和小寫字母組
成的就屬於安全的密碼了~

5 匹配一個網站中的所有連結

function get_links($link) {
    $html = file_get_contents($link);
    $html = str_replace("/n", "", $html);
    $html = preg_replace('/<a/i', "/n<a", $html);
    $html = preg_replace('/<//a>/', "</a>/n", $html);
    preg_match_all('/<a/s*.*>.*?<//a>/', $html, $matches);
    return($matches);
}


這個例子中,我們想用file_get_contents來取得一個網頁的內容。然後用str_replace("/n", "",
$html)把所有的換行去掉。再用preg_replace('/<a/i', "/n<a",
$html)和preg_replace('/<//a>/', "</a>/n", $html)來把所有的<a
href=".....">.....</a>模式另起一行。最後就用preg_match_all('/<a/
s*.*>.*?<//a>/', $html,
$matches)匹配連結模式。/<a/s*.*>.*?<//a>/就是匹配<a
href=".....">.....</a>這種模式的Regex。那我們為什麼要把<a
href=".....">.....</a>連結另起一行呢??因為在/<a/s*.*>.*?<//a>
/模式中,.*是不能匹配換行的,所以就如<a>和</a>不在同一行就不能匹配了!!所以我們要這樣做!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.