如何在Perl中很好地格式化URL?

zou*_*oul 2 url perl

我有一堆网址,我必须变成链接:

for my $url (@url_list) {
    say "<a href='$url'>$url</a>";
}
Run Code Online (Sandbox Code Playgroud)

是否有用于使可见URL更好的模块?有点像这样:

http://www.foo.com/ ? www.foo.com
http://www.foo.com/long_path ? www.foo.com/lo…

我知道一个简单的正则表达式可能会在这里做,但我被CPAN宠坏了.:)

Gre*_*con 5

RFC 2396的附录B 指定了一个解析URI引用的正则表达式.适应一点,以获得你想要的:

#! /usr/bin/perl

use warnings;
use strict;

use 5.10.0;  # for defined-or (//)

my $uri = qr{
  ^
  (?:([^:/?\#]+):)?  # scheme = $1
  (?://([^/?\#]*))?  # authority = $2
  ([^?\#]*)          # path = $3
  (\?[^\#]*)?        # query = $4
  (\#.*)?            # fragment = $5
}x;
Run Code Online (Sandbox Code Playgroud)

上面的代码使用/x修饰符

它告诉正则表达式解析器忽略大多数空格,这些空格既不是反斜杠也不是字符类.您可以使用它将正则表达式分解为(略微)更易读的部分.该#字符也被视为引入注释的元字符,就像普通的Perl代码一样.

但我们希望匹配文字#字符,如果它们存在,这意味着我需要用反斜杠来逃避它们.出于习惯,我开始使用,qr/但由于模式中的斜线,必须更改分隔符.

一些测试用例:

my @cases = qw(
  ftp://www.foo.com.invalid/
  http://www.foo.com.invalid/
  http://www.foo.com.invalid/long_path
  http://www.foo.com.invalid/?query
  http://www.foo.com.invalid?query
  http://www.foo.com.invalid/#fragment
  http://www.foo.com.invalid#fragment
);
Run Code Online (Sandbox Code Playgroud)

有点逻辑

for (@cases) {
  my $nice;
  if (my($scheme,$auth,$path,@rest) = /$uri/) {
    if ($scheme eq "http" && defined $auth) {
      if (grep defined, @rest) {
        $nice = join "" => map $_ // "" => $auth, $path, @rest;
      }
      else {
        $nice = $auth
              . ($path eq "/" ? "" : $path);
      }
    }
    else {
      $nice = $_;
    }
  }

  print "$_ ? $nice\n";
}
Run Code Online (Sandbox Code Playgroud)

和输出:

ftp://www.foo.com.invalid/ ? ftp://www.foo.com.invalid/
http://www.foo.com.invalid/ ? www.foo.com.invalid
http://www.foo.com.invalid/long_path ? www.foo.com.invalid/long_path
http://www.foo.com.invalid/?query ? www.foo.com.invalid/?query
http://www.foo.com.invalid?query ? www.foo.com.invalid?query
http://www.foo.com.invalid/#fragment ? www.foo.com.invalid/#fragment
http://www.foo.com.invalid#fragment ? www.foo.com.invalid#fragment