【问题标题】:How do I get the last directory from a URL path using a Zeus rewrite rule?如何使用 Zeus 重写规则从 URL 路径获取最后一个目录?
【发布时间】:2012-04-15 07:03:23
【问题描述】:

我需要一个正则表达式来返回路径中的最后一个目录。

例如,从www.domain.com/shop/widgets/,返回“小部件”。

我有一个几乎可以工作的表达方式。

[^/].*/([^/]+)/?$ 

它将从www.domain.com/shop/widgets/返回“小部件”,但不会从www.domain.com/widgets/返回

我还需要忽略任何包含文件名的 URL。这样www.domain.com/shop/widgets/blue_widget.html 就不会匹配了。

这必须使用正则表达式来完成,就像 Zeus 服务器请求重写模块一样。

【问题讨论】:

  • 你如何定义“文件名”?
  • $what_i_want = (split "/", $url)[-1] 也会给你答案。
  • @freespace 你读过 OP 的帖子了吗? “这必须使用 perl 正则表达式来完成,就像 Zeus 服务器请求重写模块一样。”
  • 您是否在使用 Perl Extensions for ZWS,到目前为止您为重写规则尝试了什么?

标签: regex zeus


【解决方案1】:
#!/usr/bin/perl

use strict;
use warnings;

$_ = 'www.domain.com/shop/widgets/';
print "$1\n" if (/\/([^\/]+)\/$/);

$_ = 'www.domain.com/shop/widgets/blue_widget.html';
print "$1\n" if (/\/([^\/]+)\/$/);'

【讨论】:

  • 这实际上适用于 OP 提出的所有案例(即 www.domain.com/shop/widgets/blue_widget.html 和 www.domain.com/shop/widgets/)。
  • @BluesRockAddict 除了 OP 希望它不匹配以文件名结尾的 URL - 不匹配它们并返回文件夹。 “我还需要忽略任何包含文件名的 URL”
【解决方案2】:

您不需要 Perl 正则表达式。你需要一个 Zeus 能理解的正则表达式。尽管他们可能称其为 PCRE,但 PCRE 也不能处理所有 Perl 正则表达式。

这里的大多数答案都是错误的,因为他们没有考虑您可以作为输入获得的不同类型的 URL。

  • 仅获取 URL 的路径部分
  • 匹配路径部分以找到您需要的内容
  • 区分以文件名结尾的路径和不以文件名结尾的路径

您可以使用一些示例作为开始。我不使用 Zeus 也不想使用,所以下一部分由你决定:

我了解到您可以通过 Perl Extensions for ZWS 将请求传递给 Perl 程序,但如果您需要这样做,我会感到惊讶。如果你不得不求助于它,我会使用 URI 模块来解析 URI 并提取路径。一旦你有了它,将路径分成它的组件:

use URI;

my $uri = URI->new( ... ); # I don't know how Zeus passes data
my $path = $uri->path;

# undef to handle the leading /
my( undef, @parts ) = split $path, '/';

当您走到这一步后,您必须决定如何将某物识别为目录。如果您直接映射到文件系统结构,只需从@parts 弹出元素,直到找到目录,然后倒数您要跳过的数字。

但是,无论我在 Perl 程序中添加什么内容,我都不愿意这样做。我会非常努力地首先在宙斯规则中完成它。向我们展示您目前所拥有的。

【讨论】:

    【解决方案3】:
    /^www\.example\.com\/([^\/]+\/)*([^\/]+)\/$/
    

    这是做什么的?

    • 匹配域的普通文本。根据需要进行调整。
    • 匹配任意数量的目录,每个目录由非斜线字符后跟一个斜线组成。
    • 匹配一串非斜线。
    • 匹配输入末尾的斜杠,从而消除文件(因为只有目录以斜杠结尾)。

    在 Perl 中实现:

    [ghoti@pc ~] cat perltest
    #!/usr/local/bin/perl
    
    @test = (
            'www.example.com/path/to/file.html',
            'www.example.com/match/',
            'www.example.com/pages/match/',
            'www.example.com/pages/widgets/thingy/',
            'www.example.com/foo/bar/baz/',
    );
    
    foreach (@test) {
            $_ =~ m/^www\.example\.com\/([^\/]+\/)*([^\/]+)\/$/i;
            printf(">> %-50s\t%s\n", $_, $2);
    }
    
    [ghoti@pc ~] ./perltest
    >> www.example.com/path/to/file.html                    
    >> www.example.com/match/                               match
    >> www.example.com/pages/match/                         match
    >> www.example.com/pages/widgets/thingy/                thingy
    >> www.example.com/foo/bar/baz/                         baz
    [ghoti@pc ~] 
    

    【讨论】:

    • 我没有对此投反对票,但它似乎不适用于 www.domain.com/shop/widgets/blue_widget.html 案例。
    • 为我工作。当我包含blue_widget.html 行时,它的处理方式与我的file.html 示例相同——也就是说,$2 保持未设置。你是怎么测试的?
    • 对不起 ghoti,我误读了原始问题。你的答案是正确的。
    【解决方案4】:

    这通常应该有效:

    /([^/.]+)/$
    

    它匹配必须以斜杠结尾的字符串中倒数第二个斜杠之后的一组非斜杠、非句点字符。

    “文件夹名称”将在第一个捕获组中。

    【讨论】:

    • http://www.example.com/hier/archy?f=1&y=zz/qq#frag/ment 怎么样?这里的最后一个“文件夹”可能是archy。或者qq 甚至ment,这取决于 URL 的使用方式。
    • @JamesYoungman [a] OP 的 URL 似乎使用了斜杠。 [b] 服务器级别的大多数 URL 重写引擎(OP 所询问的内容)不包含查询字符串,并且服务器永远不会看到该片段。 [c] 如果他们真的希望尾部斜杠是可选的,他们可以在模式中的最后一个 / 之后添加一个 ?
    • (还有一个事实是,这里几乎所有其他赞成的答案都做同样的事情,而且大多数效率较低。不知道为什么所有的反对意见都特别反对。)
    • 我没有对此投反对票,但它似乎不适用于 www.domain.com/shop/widgets/blue_widget.html 案例。
    • @BluesRockAddict - 这正是 OP 所要求的。 (忽略以文件名而不是文件夹结尾的 URL。)
    猜你喜欢
    • 2019-07-24
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多