可选的正则表达式段,但是如果存在要求列表?

时间:2011-10-25 13:42:35

标签: php regex

我在PHP中有一个小型路由引擎。我试图允许它可选地匹配不同的“格式”,例如对“/user/profile.json”或“/user/profile.xml”的请求。但是,它也应该只匹配一个简单的“/ user / profile”。

所以, if 如果格式存在,则必须是“.json”或“.xml”。但它根本不存在必需

这是我到目前为止所做的:

#^GET /something/([a-zA-Z0-9\.\-_]+)(\.(html|json))?$#

显然,这不起作用。这允许请求任何“格式”,因为整个格式段是可选的。如何保持可选,但约束可以请求的格式?

3 个答案:

答案 0 :(得分:4)

^GET /something/([a-zA-Z0-9._-]+)(\.(html|json))?$

允许第一个字符类中的点,因此任何文件扩展名都是合法的。我希望你是故意这样做的,因此可能有带点的文件名。

但是,这意味着如果文件名包含点,则必须以.html.json结尾。正确?

所以将正则表达式更改为(使用\w的{​​{1}}简写:

[A-Za-z0-9_]

答案 1 :(得分:2)

替代建议:

让客户端通过Accept Header in the HTTP Request(它所属的位置)指定所需的输出格式,而不是将所需的输出格式放入URL中。 Content negotiation已融入HTTP协议,因此您无需通过URL重新发送它。从技术上讲,将格式放入URL是错误的。您的URI应指向资源本身而不是资源表示。

另见W3C: Content Negotiation: why it is useful, and how to make it work

答案 2 :(得分:0)

您遇到的问题是因为大多数扩展程序都是字母数字,但在您的正则表达式中,您允许使用点和字符:

#^GET /something/[a-zA-Z0-9\.\-_]+(\.(html|json))?$#

问题部分为[a-zA-Z0-9\.\-_]+。对于.csv的例子来说,因为它仍然匹配该字符范围。

如果文件名中有点,则默认情况下,它有文件扩展名(有意或无意)。文件My.Finance.Documents的扩展名为“.Documents”,即使您将其视为文本文件或其他内容。

我讨厌这样做,但我想你可能想在你的正则表达式中有一个更大的条件,这是一个例子,我没有测试过它:

#^GET /something/([^\.]+|.*\.(?:html|json))$#

基本上,如果文件名中没有点,那就没关系。如果它确实有一个点(这保证它有一个扩展名),它必须以.html或.json结尾。