选项组内的正则表达式前瞻
我正在匹配 url,因此我可以将请求连接到控制器/视图,并且一些 url 有多个选项,其中只有一个可以在 url 中包含任何内容,但我还需要有后面的内容可作为命名组使用。
示例:
- /admin/something #match
- /admin/something/new #match
- /admin/something/new/id #失败
- /admin/something/edit #失败
- /admin /something/edit/id #match
还有很多其他可能性,但这对于一个例子来说已经足够了。 基本上,如果 url 以“new”结尾,则后面不会有任何内容,而如果以“edit”结尾,则还必须有一个要编辑的 id。
到目前为止我一直在使用的正则表达式:
^/admin/something(?:/(?P<action>new|edit(?:/(?P<id>\d{1,5}))))?$
空格分解版本:
^/admin/something(?:/
(?P<action>
new| # create a new something
edit(?:/ # edit an old something
(?P<id>\d{1,5}) # id to edit
)
)
)? # actions on something are optional
$
但是如果网址是“/admin/something/edit/id”,则“action”组是“edit/id”。 我一直在控制器中使用一点字符串操作来将动作减少到只是……动作,但我觉得积极的前瞻会更干净。 我只是无法让它发挥作用。
我一直在研究的前瞻正则表达式:(将匹配“新”,但不匹配“编辑”[有或没有 id])
^/admin/something(?:/(?P<action>new|edit(?=(?:/(?P<id>\d{1,5})))))?$
任何提示/建议将不胜感激。
I'm matching urls, so I can connect requests to controllers/views, and there are multiple options for a few of the urls, only one of which can have anything following it in the url, but I also need to have what comes after available as a named group.
Examples:
- /admin/something #match
- /admin/something/new #match
- /admin/something/new/id #fail
- /admin/something/edit #fail
- /admin/something/edit/id #match
There are many other possibilities, but thats good enough for an example. Basically, if the url ends in 'new', nothing can follow, while if it ends in 'edit' it also must have an id to edit.
The regex I've been using so far:
^/admin/something(?:/(?P<action>new|edit(?:/(?P<id>\d{1,5}))))?$
A whitespace-exploded version:
^/admin/something(?:/
(?P<action>
new| # create a new something
edit(?:/ # edit an old something
(?P<id>\d{1,5}) # id to edit
)
)
)? # actions on something are optional
$
But then if the url is '/admin/something/edit/id' the 'action' group is 'edit/id'. I've been using a little bit of string manip within the controller to cut down the action to just... the action, but I feel like a positive lookahead would be much cleaner. I just haven't been able to get that to work.
The lookahead regex I've been working at: (will match 'new', but not 'edit' [with or without an id])
^/admin/something(?:/(?P<action>new|edit(?=(?:/(?P<id>\d{1,5})))))?$
Any tips/suggestions would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的问题在于末尾的
$
。 这是正则表达式匹配到行尾的零宽度断言。 但是,您的 lookahead 也是一个零宽度断言(该 ID 遵循编辑)。 它被称为前瞻的原因是因为它在前瞻内匹配,然后跳回到该匹配的开头。 所以它在 ...edit/id 上失败,因为它试图断言 /id 跟随 edit 和 /edit 是行尾。 它仅在 ...edit 上失败,因为它试图断言 /id 遵循编辑。有两种可能的解决方案。 第一种是简单地取出$。 这可能是不可取的,因为这样它可能会匹配.../edit/id/gobbledygook。 第二种解决方案是使用正则表达式语言的重用捕获组的方法。 我无法帮助你,因为我不知道你正在使用什么正则表达式。 我无法识别命名捕获的
P
语法。 您可以将所需的任何内容放在
组之后。Your problem lies with the
$
at the end. This is a zero-width assertion that the regex matches to the end of the line. However, your lookahead is also a zero-width assertion (that id follows edit). The reason it's called a lookahead is because it matches within the lookahead, and then skips back to the beginning of that match. So it's failing on ...edit/id because it's trying to assert both that /id follows edit and /edit is the end of the line. It fails on ...edit alone because it's trying to assert that /id follows edit.There are two potential solutions. The first is to simply take out the $. This may not be desirable because then it could match .../edit/id/gobbledygook. The second solution is to use your regex language's method of reusing captured groups. I can't help you there because I don't know what regex you're using. I don't recognize the
P<name>
syntax for named capturing. You would put whatever you need for that after the<action>
group.非正则表达式方式,
non regex way,
我得到的答案使用上述两个答案中的部分来创建一个具有前瞻功能的正则表达式,该正则表达式还将我想要的所有值存储在命名组中,而没有额外的混乱,例如正斜杠。 它符合我想要的一切,但其他一切都失败了。 完美的。
我希望我可以将多个标记为答案,因为它们都帮助我找到了一条真正的道路。
The answer I came to uses parts from both of the above answers to create a regex with lookahead that also stores all the values I want in named groups, without extra clutter such as forward slashes. It matches everything I want it to, and fails everything else. Perfect.
I wish I could mark more than one as the answer, since they both helped me find the one true path.