2013-05-03 59 views
2

我想匹配PHP變量$_SERVER['SERVER_NAME']中的子域,然後執行內部重定向。 Apache或nginx重寫不是一種選擇,因爲這是客戶端/用戶可見的外部重寫。匹配子域的重定向

我的正則表達式是(.*(?<!^.))subdomain\.example\.com,您可以看到我匹配子域(多級子域)中的子域。我希望稍後使用第一個捕獲組。

這是我的PHP代碼:

if(preg_match('#(.*(?<!^.))subdomain\.example\.com#', $_SERVER['SERVER_NAME'], $match1)) { 
    echo $match1[1] . 'anothersubdomain.example.com'; 
} 

但是,如果子域是例如csssubdomain.example.com,因爲這是我不想匹配另一個子域名,這將失敗。用下面的PHP腳本我測試匹配:

$tests = array(
    'subdomain.example.com' => 'anothersubdomain.example.com', 
    'css.subdomain.example.com' => 'css.anothersubdomain.example.com', 
    'csssubdomain.example.com' => 'csssubdomain.example.com', 
    'tsubdomain.example.com' => 'tsubdomain.example.com', 
    'multi.sub.subdomain.example.com' => 'multi.sub.anothersubdomain.example.com', 
    '.subdomain.example.com' => '.subdomain.example.com', 
); 

foreach($tests as $test => $correct_answer) { 
     $result = preg_replace('#(.*(?<!^.))subdomain\.example\.com#', '$1anothersubdomain.example.com', $test); 
    echo 'Input: ' . $test . "\n" . 
     'Expected: ' . $correct_answer . "\n" . 
     'Actual : ' .$result . "\n"; 
    $passorfail = (strcmp($result, $correct_answer) === 0 ? "PASS\n\n" : "FAIL\n\n"); 
    echo $passorfail; 
} 

你會得到as output

Input: subdomain.example.com 
Expected: anothersubdomain.example.com 
Actual : anothersubdomain.example.com 
PASS 

Input: css.subdomain.example.com 
Expected: css.anothersubdomain.example.com 
Actual : css.anothersubdomain.example.com 
PASS 

Input: csssubdomain.example.com 
Expected: csssubdomain.example.com 
Actual : cssanothersubdomain.example.com 
FAIL 

Input: tsubdomain.example.com 
Expected: tsubdomain.example.com 
Actual : tsubdomain.example.com 
PASS 

Input: multi.sub.subdomain.example.com 
Expected: multi.sub.anothersubdomain.example.com 
Actual : multi.sub.anothersubdomain.example.com 
PASS 

Input: .subdomain.example.com 
Expected: .subdomain.example.com 
Actual : .subdomain.example.com 
PASS 

奇怪的是,它匹配csssubdomain.example.com但不tsubdomain.example.com

有人知道你可以用這種情況下的正則表達式嗎?我嘗試了一些與lookahead and lookbehind zero-width assertions的事情,但它並沒有真正的工作。如果允許這種.toto.subdomain.example.com

~^((?:\w+\.)*?)subdomain\.example\.com~ 

,只是在開頭添加\.?

回答

1

你可以試試這個模式

~^((?:\.?\w+\.)*?)subdomain\.example\.com~ 

,如果你想允許一個連字符只需將其添加到字符分類:

~^((?:\.?[\w-]+\.)*?)subdomain\.example\.com~ 

如果你不允許su bstring開始或結束與一個hypen字符:

~^((?:\.?\w+([\w-]*?\w)?\.)*?)subdomain\.example\.com~ 
+0

謝謝你完美的作品!關於具有「連字符」(te-st.example.com)的子域,只有一件事情?見:http://regexr.com?34ose – user1480019 2013-05-04 11:01:47

+1

@GerritHoekstra:試試這個編輯,我去睡覺。 – 2013-05-04 11:12:20