【问题标题】:Regex to rewrite urls with one or more key/value pairs正则表达式用一个或多个键/值对重写 url
【发布时间】:2013-01-06 14:54:15
【问题描述】:

您能否建议一个正则表达式来重写以下网址:

http://intranet/myApp/index.cfm/go:welcome.home/fruit:orange/car:ford/age:37/music:rock

到这里:

http://intranet/myApp/index.cfm?go=welcome.home&fruit=orange&car=ford&age=37&music=rock

它需要能够满足任意数量的不同定义的 url 参数。

目前,我只能设法匹配/替换第一个 url 参数。

    <rule>
        <from>/index\.cfm/go:([^:/]*){1}</from>
        <to>/index.cfm?go=$1</to>
    </rule>

不确定是否可以在它们存在的地方添加“:”到“=”和“/”到“&”的后续替换。

谢谢

【问题讨论】:

  • 发件人:/index\.cfm/go:([^:/]*)/fruit:([^:/]*)/car:([^:/]*)/age:([^:/]*)/music:([^:/]*) 收件人:/index.cfm?go=$1&amp;fruit=$2&amp;car=$3&amp;age=$4&amp;music=$5,如果参数始终按该顺序排列,则应该可以工作。
  • 您也可以重定向到一个 php 页面,该页面将在 $_GET 查询字符串中使用这些变量值对重新重定向到该页面。
  • 我能做的最好的事情是 (\b/(\w*):(\w*)\b)?(\b/(\w*):(\w *)\b)?被 &$3=$4&$6=$7 替换,这既混乱又有限,并且添加了尾随不需要的字符(我相信会被忽略)。
  • 您对&lt;rule&gt; 的使用表明您无法控制转换的完成方式。您将 XML 提供给什么? 必须是正则表达式解决方案吗?
  • 我将正则表达式输入到 urlrewrite.xml 作为 urlRewriteFilter tuckey.org/urlrewrite 的一部分

标签: regex url-rewriting tuckey-urlrewrite-filter


【解决方案1】:

与解析 HTML 一样,处理 URI 最好使用库来处理许多极端情况和格式复杂性。在这种情况下,使用非常常见的URI library 将 URI 拉开并重新组合在一起。

#!/usr/bin/env perl

use strict;
use warnings;

use Test::More;

use URI;

sub path_to_query_string {
    my $uri  = shift;
    my $file = shift;

    # Turn it into a URI object if it isn't already.
    $uri = URI->new($uri) unless eval { $uri->isa("URI"); };

    # Get the path all split up.
    my @path_pairs = $uri->path_segments;

    # Strip everything up to what is the real filename.
    my @path;
    while(@path_pairs) {
        push @path, shift @path_pairs;
        last if $path[-1] eq $file;
    }

    # Put the path bits back.
    $uri->path_segments(@path);

    # Split each key/value pair
    my @pairs;
    for my $pair (@path_pairs) {
        push @pairs, split /:/, $pair;
    }

    # Put them back on the URI
    $uri->query_form(\@pairs);

    return $uri;
}

my %test_urls = (
    "http://intranet/myApp/index.cfm/go:welcome.home/fruit:orange/car:ford/age:37/music:rock" =>
      "http://intranet/myApp/index.cfm?go=welcome.home&fruit=orange&car=ford&age=37&music=rock"
);

for my $have (keys %test_urls) {
    my $want = $test_urls{$have};
    is path_to_query_string($have, "index.cfm"), $want, "path_to_query_string($have)";
}

done_testing;

【讨论】:

    【解决方案2】:

    如果您不能在“to”中包含除插值之外的代码,则不能。不过,您可以生成一大堆规则。

    my $MAX_ARGS = 20;
    my ($p, $q);
    for (1..$MAX_ARGS) {
        $p .= sprintf('/([^:/]+){%d}:([^/]*){%d}', $_+0, $_+1);
        $q .= sprintf('&$%d=$%d',                  $_+0, $_+1);
        $q =~ s/^&/?/;
        print <<"__EOI__";
        <rule>
            <from>/index\.cfm$p</from>
            <to>/index.cfm?$q</to>
        </rule>
    __EOI__
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 2011-09-03
      • 1970-01-01
      • 2011-01-26
      相关资源
      最近更新 更多