2012-04-07 64 views
0

我試圖在Ruby中使用正則表達式來分解標準RESTful URI。遞歸命名捕獲:解析RESTful URI

假設我們正在製作音樂唱片公司的Web應用程序。我們有許多藝術家,其中有很多專輯,有許多歌曲。

採用這種設置,下面的RESTful的URI應該都可以作爲GET請求:

/artists 
/artists/1 
/artists/1/albums 
/artists/1/albums/1 
/artists/1/albums/1/songs 
/artists/1/albums/1/songs/1 
/artists/1/albums/1/songs/1/artists 
/artists/1/albums/1/songs/1/artists/1 

在試圖捕捉使用正則表達式這些URI,我颳起了以下(live example):

^\/(?<resource>(?:artists|albums|songs))(?:\/(?<id>\d+))?\/?$ 

當給定一個根級的資源,如下面的正則表達式作品預計:

/artists 
/songs/1 

第一個結果匹配數據的資源爲artists,ID爲nil,第二個資源爲songs,ID爲1

但是,當給定一個URI請求資源的關聯,如/albums/1/songs/1,這個正則表達式將失敗,因爲如果不考慮遞歸。所以,我把整個事情在非捕獲組以「一個或多個」(+)就可以了預選賽:

^(?:\/(?<resource>artists|albums|songs)(?:\/(?<identifier>\d+))?)+\/?$ 

這個規則表達式現在能對URI的如/albums/1/songs/2但由此產生的matchdata只包含最後資源(songs)和id(2)。
我在期待一個包含兩個對象的數組,其中一個的資源爲albums,另一個的資源爲songs

在正在使用「一個或多個」限定符的捕獲組中有正確使用命名捕獲的方法嗎?

+0

有些人在遇到問題時,認爲 「我知道,我會用正則表達式。」現在他們有兩個問題。 – 2012-04-07 14:41:35

+4

*有些人遇到正則表達式時,會想「我知道,我會用我記得的引人入勝的引語」。 * - Tomalak – 2012-04-07 15:12:10

+0

*無論如何,這只是我對濫用正則表達式的人的直覺反應。* --MITTYБДLL。 – 2012-04-07 17:41:38

回答

0

大部分正則表達式並不適合這種方式。每個捕獲組只包含它匹配的最後一個子字符串。 除非你使用.NET regex lib,它記住捕獲組的每一個匹配。

0

「遞歸」對於您遇到的問題並不是真正正確的詞彙。您試圖在您的正則表達式中遍歷多個/resource/id對,然後檢索單個捕獲。我建議你使用這個表達式來代替:

\/(?<resource>artists|albums|songs)(?:\/(?<identifier>\d+))? 

...並遍歷/resource/id對在你的代碼(例如,與scan方法)。

+0

問題在於例如'/ song/1foo/bar'仍然會匹配。因此需要預驗證步驟,或者使用'\ G'並確保匹配位置是所有匹配後所希望的位置。 – Qtax 2012-04-07 17:02:02