2012-04-01 56 views
4

前一段時間我問了一個關於使用正則表達式從特定目錄中的URL中提取匹配的問題。如何使用正則表達式排除目錄?

如:www.domain.com/shop/widgets/match/

給出的解決方案是^/shop.*/([^/]+)/?$

這將返回"match"

然而,我的文件結構發生了變化,我現在需要的是,而不是在任何目錄中排除"pages"返回"match"表達和"system"

基本上我需要一個表達式,將返回"match"以下:

www.domain.com/shop/widgets/match/ 
www.domain.com/match/ 

但不是:

www.domain.com/pages/widgets/match/ 
www.domain.com/pages/ 

www.domain.com/system/widgets/match/ 
www.domain.com/system/ 

我一直在掙扎了好幾天沒有任何運氣。

謝謝

+4

爲什麼不只是使用兩個正則表達式,一個是你現在使用的,另一個用來檢查URL中是否有「pages」或「system」這個單詞。 – 2012-04-01 04:13:11

+0

'^/shop。* /([^ /] +)/?$'完全不符合「www.domain.com/shop/widgets/match /」。然而,它會匹配'/ shop/widgets'。您可以使用'/^[a-z0-9 .-] + \/shop \/[^ \ /] + \ /([^ \ /] +)\/$ /'從該URL中提取「匹配」段爲'\ 1'。我正在跳過斜槓,因爲我也使用斜線作爲分隔符。如果您不需要分隔符,則不需要跳過斜槓。 – Graham 2012-04-01 04:14:19

+0

@jb嘿,這是一個好主意。我會放棄這一點。但我很想看到它是如何在一個表達式中完成的。 – Matt 2012-04-01 04:29:00

回答

2

這只是格拉姆斯上面的一個很好的選擇。代碼在C#(但FOT正則表達式的一部分,這並不重要):

void MatchDemo() 
{ 
    var reg = new Regex("(     " + 
         " (\\w+[.])  " + 
         " |    " + 
         " (\\w+[/])+  " + 
         ")     " + 
         "(shop[/]|\\w+[/]) " +    //the URL-string must contain the sequence "shop" 
         "(match)   " , 
         RegexOptions.IgnorePatternWhitespace); 

    var url = @"www.domain.com/shop/widgets/match/"; 

    var retVal = reg.Match(url).Groups[5];      //do we have anything in the fifth parentheses? 

    Console.WriteLine(retVal); 
    Console.ReadLine(); 
} 

/漢斯

2

BRE和ERE不提供一種方式來否定RE的一部分,除正方形內括號表達。也就是說,你可以[^a-z],但是你不能表示而不是/(abc|def)/。如果你的正則表達式是ERE,那麼你的必須使用兩個正則表達式。如果您使用PREG,則可以使用負面預測。

例如,這裏的一些PHP:

#!/usr/local/bin/php 
<?php 

$re = '/^www\.example\.com\/(?!(system|pages)\/)([^\/]+\/)*([^\/]+)\/$/'; 

$test = array(
    'www.example.com/foo/bar/baz/match/', 
    'www.example.com/shop/widgets/match/', 
    'www.example.com/match/', 
    'www.example.com/pages/widgets/match/', 
    'www.example.com/pages/', 
    'www.example.com/system/widgets/match/', 
    'www.example.com/system/', 
); 

foreach ($test as $one) { 
    preg_match($re, $one, $matches); 
    printf(">> %-50s\t%s\n", $one, $matches[3]); 
} 

和輸出:

[[email protected] ~]$ ./phptest 
>> www.example.com/foo/bar/baz/match/     match 
>> www.example.com/shop/widgets/match/     match 
>> www.example.com/match/        match 
>> www.example.com/pages/widgets/match/     
>> www.example.com/pages/        
>> www.example.com/system/widgets/match/     
>> www.example.com/system/   

這就是你想要的?