递归命名捕获:解析RESTful URI

时间:2012-04-07 14:18:56

标签: regex url rest uri

我正在尝试使用Ruby中的正则表达式来分解标准的RESTful URI。

假设我们正在制作音乐唱片网络应用程序。我们有很多艺术家,有很多专辑,有很多歌曲。

使用此设置,以下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

为了尝试使用Regexp捕获这些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+))?)+\/?$

此正则表达式现在适用于/albums/1/songs/2等URI,但生成的匹配数据仅包含最后一个资源(songs)和id(2)。 我期待一个包含两个对象的数组,一个资源为albums,另一个资源为songs

在使用“一个或多个”限定符的捕获组中是否有正确使用命名捕获的方法?

2 个答案:

答案 0 :(得分:0)

大多数正则表达式都不会那样。每个捕获组仅包含它匹配的最后一个子字符串。 除非您使用.NET regex lib,它会记住捕获组的每个匹配项。

答案 1 :(得分:0)

“递归”对于你遇到的问题来说并不是一个正确的词。您正试图在正则表达式中迭代多个/resource/id对,然后检索单个捕获。我建议你改用这个正则表达式:

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

...并迭代代码中的/resource/id对(例如,使用scan方法)。