程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 正則表達式-非

正則表達式-非

編輯:關於PHP編程

我們使用正則表達式,熟練掌握各種功能和結構只是手段,解決實際的問題才是真正的目的。要解決真正的問題,就必須有解決問題的思路,正則表達式的功能,說到底,可以歸納為三種邏輯,為了表述方便,我們分別稱為與、或、非。

最近用CI在做個人工資管理系統的時候,需要驗證用戶是否登錄和使用特定的功能,用到了正則表達式-非。需求如下:

路徑/user, /user/login, /user/register不需要進行攔截,其實諸如/profile, /company, /work的路徑都要攔截,然後檢查session中是否存在user_id,沒有的話就跳轉到/user/login

初步觀察:

只要對/user進行匹配就行了。初步代碼如下:

01
<?php
02
class Acl {
03
 
04
    private $CI;
05
 
06
    public function __construct() {
07
        $this->CI = &get_instance();
08
    }
09
 
10
    public function auth() {
11
        if (!preg_match('/^user.*$/', uri_string())) {
12
            $user_id = $this->CI->session->userdata('user_id');
13
            if(empty($user_id)) {
14
                redirect('/user');
15
                return;
16
            }
17
        }
18
    }
19
}
測試的時候才發現漏了檢測user/change_password,這個功能是需要客戶首先登錄的,這裡就要在user.*中排除user/change_password的,也就是前面說的要用到正則中的“非”。

“非”是正則表達式中最難處理的邏輯關系。因為沒有直接對應的結構,“非”的處理比較吃力。

最簡單的“非”,意思是此處不能出現某個字符,這一點通常很直觀,似乎用排除型字符組[^…]就可以解決。比如雙引號字符串的匹配,首尾兩個雙引號很容易匹配,其中的內容肯定不是雙引號(暫時不考慮轉義的情況),所以可以用[^"]表示即可,其長度不確定,所以用*來限定,所以整個表達式就是"[^"]*",非常簡單。

但是,事情果真都如此簡單嗎?我們舉cat和cut的例子,如果希望匹配c開頭,t結尾的單詞,但不希望匹配cut,可以寫成c[^u]t,是否就可以了?

這個表達式的意思是:最開頭的字母是c,之後是一個不為u的字符,之後是t。沒錯,它確實不會匹配cut,也可以匹配cat。但是,chart、conduct、court等等,它也沒法匹配,因為[^u]的意思是:匹配一個不是u的字符。

那麼,把[^u]改成[^u]+好了,這樣應該就可以解決問題了。但是真的如此嗎?[^u]+的意思是,一個或若干(最多到無窮)個字符,但每一個字符都不能是u。所以,盡管c[^u]+t能匹配cat和chart,卻不能匹配conduct和court。

其實cut和我的路徑匹配問題可以用順序否定環視功能來解決。

(?!cut)就是用來進行這種判斷的,它判斷之後的字符串能不能由cut匹配,也不會移動“當前位置”。所以我們將它放在表達式的最開頭,得到(?!cut)c[a-z]+t。這個表達式的邏輯是:只有在當前位置右側字符串不能由cut匹配的情況下,才從這裡開始,向右嘗試用c[a-z]+t。

如果我們更進一步,需要排除掉cat和cut,可以把否定順序環視改為(?!c[au]t)。這樣就能保證,匹配到的肯定不是cat或者cut。www.2cto.com

 

回到最上面的問題。直接上代碼吧,代碼如下:
 
01
<?php
02
class Acl {
03
 
04
    private $CI;
05
 
06
    public function __construct() {
07
        $this->CI = & get_instance();
08
    }
09
 
10
    public function auth() {
11
        if (!preg_match('/^(?!user\/change_password)user.*$/', uri_string())) {
12
            $user_id = $this->CI->session->userdata('user_id');
13
            if(empty($user_id)) {
14
                redirect('/user');
15
                return;
16
            }
17
        }
18
    }
19
}
作者:kxt

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved