【问题标题】:Recursive named captures: Parsing a RESTful URI递归命名捕获:解析 RESTful URI
【发布时间】:2012-04-07 14:18:56
【问题描述】:

我正在尝试使用 Ruby 中的正则表达式分解标准 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

为了尝试使用 Regexp 捕获这些 URI,我创建了以下内容 (live example):

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

当给定如下的根级资源时,正则表达式按预期工作:

/artists
/songs/1

第一个结果匹配数据的资源为artists,id 为nil,第二个的资源为songs,id 为1

但是当给定一个请求资源关联的 URI 时,例如 /albums/1/songs/1,这个正则表达式将失败,因为 if 不考虑递归。所以,我把整个东西扔到一个非捕获组中,上面带有“一个或多个”(+) 限定符:

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

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

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

【问题讨论】:

  • 有些人在遇到问题时会想“我知道,我会使用正则表达式。”。现在他们有两个问题。
  • 有些人在遇到正则表达式时会想“我知道,我会使用我记得的引人入胜的引语”。现在他们没有在讨论中添加任何内容。 -- Tomalak
  • 无论如何,这只是我对人们滥用正则表达式的直觉反应。 --MДΓΓ БДLL。

标签: regex url rest uri


【解决方案1】:

大多数正则表达式风格都不是这样工作的。每个捕获组将只包含它匹配的最后一个子字符串。 除非您使用 .NET 正则表达式库,它会记住捕获组的每个匹配项。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 问题例如/song/1foo/bar 仍然匹配。因此需要一个预验证步骤,或者使用\G 并确保匹配位置在所有匹配之后您想要的位置。
    猜你喜欢
    • 2017-09-06
    • 2011-05-05
    • 2015-08-03
    • 2011-10-10
    • 2016-03-08
    • 1970-01-01
    • 2013-01-23
    • 2018-09-30
    • 2012-08-11
    相关资源
    最近更新 更多