正则表达式 – 解析mysql:/// sqlite:/// URL

前端之家收集整理的这篇文章主要介绍了正则表达式 – 解析mysql:/// sqlite:/// URL前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们在一个模块中有这个小正则表达式来解析以下URL:

if( my ($conn,$driver,$user,$pass,$host,$port,$dbname,$table_name,$tparam_name,$tparam_value,$conn_param_string) =
    $url =~ m{^((\w*)://(?:(\w+)(?:\:([^/\@]*))?\@)?(?:([\w\-\.]+)(?:\:(\d+))?)?/(\w*))(?:/(\w+)(?:\?(\w+)=(\w+))?)?((?:;(\w+)=(\w+))*)$} ) {

MysqL的://anonymous@my.self.com:1234 / DBNAME

现在我们要添加sqlite URL的解析,如下所示:

sqlite的:/// dbname_which_is_a_file

但它不适用于绝对路径,如:sqlite:/// tmp / dbname_which_is_a_file

这样做的正确方法是什么?

解决方法

正则表达式的问题是,对于长度超过两个元素的路径不起作用.它将它们拆分为db_name和table_name(如果有).此正则表达式也不适用于sqlite特殊文件名,如’:memory'(对于测试非常有用).

为了获得可维护的RE方法,使用它的最佳方法是使用一个调度表,其中包含需要不同解析的主要协议,并为每种不同的方法设置一个子程序.还有一个带有// x的RE,所以它可以有注释并帮助它的可维护性:

sub test_re{
     my $url =shift;
     my $x={};
     @$x{qw(conn driver user pass host port dbname table_name tparam_name tparam_value conn_param_string)} =
         $url =~ m{
                ^(
                  (\w*)
                  ://
                  (?:
                    (\w+) # user
                    (?:
                      \:
                      ([^/\@]*) # password 
                    )?
                    \@
                  )? # could not have user,pass
                  (?:
                    ([\w\-\.]+) #host
                    (?:
                      \:
                      (\d+) # port
                    )? # port optional
                  )? # host and port optional
                  / # become in a third '/' if no user pass host and port
                  (\w*) # get the db (only until the first '/' is any). Will not work with full paths for sqlite.
                )
                (?:
                  /  # if tables
                  (\w+) # get table
                  (?:
                    \? # parameters
                    (\w+)
                    =
                   (\w+)
                  )? # parameter is conditional but would have always a tablename
                )? # conditinal table and parameter
                (
                  (?:
                    ;
                    (\w+)
                    =
                    (\w+)
                  )* # rest of parameters if any
                )
                $
             }x;
     return $x;
 }

但我建议使用URI::Split(比URI更少的代码详细程度),然后根据需要拆分路径.

您可以在此处看到使用RE与URI :: Split的区别:

#!/usr/bin/env perl

use feature ':5.10';
use strict;
use URI::Split qw(uri_join uri_split);
use Data::Dumper;

my $urls = [qw(
             MysqL://anonymous@my.self.com:1234/dbname
             MysqL://anonymous@my.self.com:1234/dbname/tablename
             MysqL://anonymous@my.self.com:1234/dbname/pathextra/tablename
             sqlite:///dbname_which_is_a_file
             sqlite:///tmp/dbname_which_is_a_file
             sqlite:///tmp/db/dbname_which_is_a_file
             sqlite:///:dbname_which_is_a_file
             sqlite:///:memory
             )];



foreach my $url (@$urls) {
    print Dumper(test_re($url));
    print Dumper(uri_split($url));
}

结果:

[...]
 == testing sqlite:///dbname_which_is_a_file ==
 - RE
 $VAR1 = {
           'pass' => undef,'port' => undef,'dbname' => 'dbname_which_is_a_file','host' => undef,'conn_param_string' => '','conn' => 'sqlite:///dbname_which_is_a_file','tparam_name' => undef,'tparam_value' => undef,'user' => undef,'table_name' => undef,'driver' => 'sqlite'
         };

 - URI::Split
 $VAR1 = 'sqlite';
 $VAR2 = '';
 $VAR3 = '/dbname_which_is_a_file';
 $VAR4 = undef;
 $VAR5 = undef;

 == testing sqlite:///tmp/dbname_which_is_a_file ==
 - RE
 $VAR1 = {
           'pass' => undef,'dbname' => 'tmp','conn' => 'sqlite:///tmp','table_name' => 'dbname_which_is_a_file','driver' => 'sqlite'
         };

 - URI::Split
 $VAR1 = 'sqlite';
 $VAR2 = '';
 $VAR3 = '/tmp/dbname_which_is_a_file';
 $VAR4 = undef;
 $VAR5 = undef;

== testing sqlite:///tmp/db/dbname_which_is_a_file ==
- RE
$VAR1 = {
          'pass' => undef,'dbname' => undef,'conn_param_string' => undef,'conn' => undef,'driver' => undef
        };

- URI::Split
$VAR1 = 'sqlite';
$VAR2 = '';
$VAR3 = '/tmp/db/dbname_which_is_a_file';
$VAR4 = undef;
$VAR5 = undef;

== testing sqlite:///:memory ==
- RE
$VAR1 = {
          'pass' => undef,'driver' => undef
        };

- URI::Split
$VAR1 = 'sqlite';
$VAR2 = '';
$VAR3 = '/:memory';
$VAR4 = undef;
$VAR5 = undef;

猜你在找的正则表达式相关文章