凌乱的URL更有效的RewriteRule

时间:2013-07-12 03:16:03

标签: regex url-rewriting

我开发了一个新网站来替换客户端的现有网站。他们以前的网站有一些非常讨厌的URL到他们的产品。例如,旧网址:

http://mydomain.com/p/-3-0-Some-Ugly-Product-Info-With-1-3pt-/a-arbitrary-folder/-18pt/-1-8pt-/ABC1234

我想抓住所有使用这些旧网址的新网站的请求。我需要的旧网址信息是ABC1234,它是产品ID。为了澄清,旧网址以/p/开头,后跟四个级别的文件夹,然后是产品ID。

例如,上面的URL需要重写为:

http://mydomain.com/shop/?sku=ABC1234

我在Linux上使用Apache 2.2。任何人都可以指出我正确的模式匹配?我知道这是错的,但我现在正处于这里:

RewriteRule ^p/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)?$ shop/?sku=$5 [R=301,NC,L]

我很确定用于匹配4个文件夹中每个文件夹的模式是多余的,但我对正则表达式并不那么敏锐。我试过一些在线正则表达式评估员但没有成功。

谢谢。

- 编辑#1 -

实际上,我上面的RewriteRule确实有效,但有没有办法缩短它?

- 编辑#2 -

感谢ddr,我已经能够将这个表达式归结为:

RewriteRule ^p/([\w-]+/){4}([\w-]+)$ shop/?_sku=$2 [R=301,NC,L]

- 编辑#3 -

主要是为了ddr的利益,但我欢迎任何人帮助谁。我正在处理超过10,000个需要重写的URL才能使用新站点。到目前为止我提供的信息仍然存在,但现在我正在测试所有旧URL正在被正确重写我遇到了一些不适用于ddr提供的RewriteRule示例的异常。

旧的URL是一致的,因为我需要的产品ID位于URL的最末端,如上所述。第一个文件夹始终为/p/。我在这一点上遇到的问题是,一些URL有一个URL编码的双引号(“)。此外,一些URL包含一个/ - /作为提到的四个文件夹之一。所以这里有一些例子旧网址的变体:

/p/-letters-numbers-hyphens-88/another-folder/-and-another-/another-18/ABC1234

/p/-letters-numbers-hyphens-88/2%22/-/-/ABCD1234

/p/letters-numbers-hyphens-1234/34-88/-22/-/ABCD1234/

虽然旧的网址很糟糕,但我认为可以说以下内容始终是正确的:

  • 每个都以/ p /
  • 开头
  • 每个都以我需要隔离的产品ID结束。
  • / p /和产品ID之间总是有四个级别的文件夹。
  • 中间的某些文件夹有连字符,有些没有。
  • 中间的某些文件夹只是连字符。
  • 介于两者之间的某些文件夹包含一个%字符,用于对其进行网址编码。
  • 有些请求最后包含/,有些则不包括。

以下规则由ddr提供并且运行良好,直到我遇到包含%百分号的网址或仅包含连字符的文件夹:

RewriteRule ^p/(?:[\w-]+/){4}([\w-]+)$ shop/?_sku=$1 [R=301,NC,L]

根据上述规则,如何编辑它以允许仅限连字符(/ - /)或百分号的文件夹?

1 个答案:

答案 0 :(得分:2)

您可以使用字符类来减少一些长度。除了最后一个,括号(捕获组)也是不必要的,正如@jpmc26所说。

我对Apache规则并不是特别熟悉,但试试这个:

RewriteRule ^p/(?:[\w-]+/){4}([\w-]+)$ shop/?sku=$1 [R=301,NC,L]

如果支持扩展正则表达式,它应该有效。

  • \w相当于[A-Za-z0-9_],您不需要捕获下划线,因此这是一个替代品。
  • {4}恰好匹配前一组的四次重复。这并不总是支持,因此Apache可能不喜欢它。
  • ?:是可选的,但表示不应将这些parens视为捕获。使它更有效率。

我不确定[]最后的部分是什么,但是我离开了。我无法理解为什么在?之前需要$,所以我把它拿出来了。

编辑:如果Apache喜欢它,最紧凑的方式可能是

RewriteRule ^p(/[\w-]+){5}$ shop/?sku=$5 [R=301,NC,L]

编辑:回复编辑问题3。

我很惊讶它只适用于-。即使只有一个[\w-]+-也应匹配。您确定这些网址中没有其他内容吗?

您也可以尝试使用-替换正则表达式中的\-

至于%,只需将[\w-]更改为[\w%-]即可。确保最后留下-!否则,正则表达式引擎将尝试将其解释为char序列的一部分。

编辑2:或试试这个: RewriteRule ^p/(?:.*?/){4}(.*?)/?$ shop/?sku=$1 [R=301,NC,L]