【问题标题】:Can I use mod_rewrite to redirect to a URL with a zero-padded parameter?我可以使用 mod_rewrite 重定向到带有零填充参数的 URL 吗?
【发布时间】:2010-11-20 04:03:38
【问题描述】:

我正在尝试使用 mod_rewrite 将 URL 从旧主机的 URL 重定向到使用不同 URL 格式的新主机。新主机将 ID 补零为六位数,如下所示:

旧网址:

http://www.example.com/script.cgi?page_id=123

需要重定向到:

http://archive.example.com/000123/

这是我目前所拥有的:

RewriteCond %{QUERY_STRING} ^page_id=([0-9]+)$
RewriteRule ^script\.cgi http://archive.example.com/%1/? [R=301,L]

这是重定向到:

http://archive.example.com/123/

有什么方法可以使用 mod_rewrite 实现零填充,还是我只需要编写一个处理程序脚本来重定向到正确的 URL?

【问题讨论】:

  • 这看起来应该是服务器故障。

标签: .htaccess mod-rewrite redirect query-string


【解决方案1】:

这里有两个更优雅的解决方案:

  1. 使用N flag 一次加一个零,直到得到六位数:

    RewriteCond %{QUERY_STRING} ^(([^&]*&)*)page_id=([0-9]{1,5})(&.*)?$
    RewriteRule ^script\.cgi$ $0?page_id=0%3 [N]
    RewriteCond %{QUERY_STRING} ^([^&]*&)*page_id=([0-9]{6})(&.*)?$
    RewriteRule ^script\.cgi$ http://archive.example.com/%2/? [R=301,L]
    
  2. 使用额外的RewriteCond 前置五个零,然后只得到最后六个数字:

    RewriteCond %{QUERY_STRING} ^(([^&]*&)*)page_id=([0-9]+)(&.*)?$
    RewriteCond 00000%3 [0-9]{6}$
    RewriteRule ^script\.cgi$ http://archive.example.com/%0/? [R=301,L]
    

QUERY_STRING 上应用的复杂模式只是为了考虑额外的 URL 参数。我更喜欢第二种解决方案,因为它只是一个规则并且更全面。

【讨论】:

    【解决方案2】:

    不是一个优雅的解决方案,但您可以设置六种不同的规则:

    RewriteCond %{QUERY_STRING} ^page_id=([0-9]{1})$
    RewriteRule ^script\.cgi http://archive.example.com/00000%1/? [R=301,L]
    
    RewriteCond %{QUERY_STRING} ^page_id=([0-9]{2})$
    RewriteRule ^script\.cgi http://archive.example.com/0000%1/? [R=301,L]
    
    RewriteCond %{QUERY_STRING} ^page_id=([0-9]{3})$
    RewriteRule ^script\.cgi http://archive.example.com/000%1/? [R=301,L]
    
    RewriteCond %{QUERY_STRING} ^page_id=([0-9]{4})$
    RewriteRule ^script\.cgi http://archive.example.com/00%1/? [R=301,L]
    
    RewriteCond %{QUERY_STRING} ^page_id=([0-9]{5})$
    RewriteRule ^script\.cgi http://archive.example.com/0%1/? [R=301,L]
    
    RewriteCond %{QUERY_STRING} ^page_id=([0-9]+)$
    RewriteRule ^script\.cgi http://archive.example.com/%1/? [R=301,L]
    

    【讨论】:

    • 打败我!我想这可能是唯一的方法。至少只有六位数。
    【解决方案3】:

    另一种选择是使用 RewriteMap 并让脚本生成要重定向到的 URL。

    RewriteMap zeropad prg:/usr/local/zeropad.pl
    
    RewriteCond %{QUERY_STRING} ^page_id=([0-9]+)$
    RewriteRule ^script\.cgi ${zeropad:%1} [R=301,L]
    

    而 /usr/local/zeropad.pl 是一个可执行脚本,包含类似

    #!/usr/bin/perl
    $| = 1; #We don't want buffering
    while (<STDIN>) {
        printf("http://archive.example.com/%06d/?\n",$_);
    }
    

    你可以使用任何你喜欢的可执行文件来代替 Perl 的。这个想法是让它打印出(带有尾随换行符)要重定向到的 URL。它必须在读取 STDIN 的循环中工作,因为 Apache 将启动脚本一次并重复调用同一个实例。它无法缓冲其输出,因为 Apache 将在完成重写之前等待其输出(直到换行)。

    【讨论】:

      【解决方案4】:

      好的,我意识到我可以通过以下方式实现我想要的结果:

      RewriteCond %{QUERY_STRING} ^page_id=([0-9]{1})$
      RewriteRule ^script\.cgi http://archive.example.com/00000%1/? [R=301,L]
      
      RewriteCond %{QUERY_STRING} ^page_id=([0-9]{2})$
      RewriteRule ^script\.cgi http://archive.example.com/0000%1/? [R=301,L]
      
      RewriteCond %{QUERY_STRING} ^page_id=([0-9]{3})$
      RewriteRule ^script\.cgi http://archive.example.com/0000%1/? [R=301,L]
      
      RewriteCond %{QUERY_STRING} ^page_id=([0-9]{4})$
      RewriteRule ^script\.cgi http://archive.example.com/00%1/? [R=301,L]
      
      RewriteCond %{QUERY_STRING} ^page_id=([0-9]{5})$
      RewriteRule ^script\.cgi http://archive.example.com/0%1/? [R=301,L]
      
      RewriteCond %{QUERY_STRING} ^page_id=([0-9]{6})$
      RewriteRule ^script\.cgi http://archive.example.com/%1/? [R=301,L]
      

      如果没有多个规则,还有其他方法可以做到这一点吗?

      【讨论】:

      • 所以 StackOverflow 已经安装了新的心灵感应插件 :)
      猜你喜欢
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 2014-06-16
      • 2010-11-20
      • 2022-01-08
      • 1970-01-01
      相关资源
      最近更新 更多