使用Perl正则表达式确定URI是否有效

ste*_*esu 3 regex perl escaping

对于我正在开发的应用程序,我需要一个Perl脚本,它循环遍历一个大量的CSV文件,并确保每一行包含一个有效的URI.我之前已经问过一个关于解析CSV文件的问题,我已经开始使用它Text::CSV来让我的生活变得更轻松.现在我遇到了确保URI有效的问题.

由于我的应用程序的性质,URI不需要采取完整的形式

protocol://username:password@domain.extension/request?vars=values
Run Code Online (Sandbox Code Playgroud)

相反,我只对这个请求部分感兴趣.对于一般的网站,这将是以后的事情.com,.edu等等.

我目前有以下Perl脚本:

if($_ !~ /^(?:[a-z0-9-._~!$&'()*+,;=:/?@]|%[0-9A-F]{2})*$/i){
    print "Invalid URL format";
    exit;
} else {
    /* stuff */
}
Run Code Online (Sandbox Code Playgroud)

正则表达式应该是相当直接的.允许请求包含一小组符号([a-z0-9-._~!$&'()*+,;=:/?@])中的一个,或者它可以包含百分号(%),后跟两个十六进制数字.这些模式中的任何一个都可以无限重复.

当我运行此脚本时,我收到以下错误:

Number found where operator expected at ./301rules.pl line 58, near "%[0"
        (Missing operator before 0?)
Bareword found where operator expected at ./301rules.pl line 58, near "9A"
        (Missing operator before A?)
Bareword found where operator expected at ./301rules.pl line 58, near "$/i"
        (Missing operator before i?)
syntax error at ./301rules.pl line 58, near "%[0"
Run Code Online (Sandbox Code Playgroud)

很明显,我的正则表达式中的某些内容需要被转义,但我不确定是什么.我试图转义每个可能的符号来创建以下正则表达式:

if($_ !~ /^(?:[a-z0-9\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=\:\/\?\@]|%[0-9A-F]{2})*$/i){
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时,它只允许每个字符串通过测试,即使是我知道无效的字符串,如te%sté

那么有没有人有Perl正则表达式的经验,知道我需要逃避什么以及我不应该逃避什么?有19个不同的符号,我不觉得尝试所有2 ^ 19 = 524288的可能性.

编辑 - 投票结束.我发现问题实际上存在于此循环之上,尽管我还不完全理解为什么.

我有:

if( $_ == "" ){
    next;
}
/* regex conditional from above */
Run Code Online (Sandbox Code Playgroud)

无论出于什么原因,它仍然会评估为真,并进入下一次迭代,尽管显然存储了数据$_.我会弄清楚为什么会这样,但是现在这个正则表达式可以正常运行.

Dav*_*idO 5

URI模块的文档中,我发现了以下内容:

PAREXING URI与REGEXP

作为此模块的替代,可以使用以下(官方)正则表达式来解码URI:

    my($scheme, $authority, $path,
    $query, $fragment) =   $uri =~
    m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
Run Code Online (Sandbox Code Playgroud)

URI :: Split模块提供函数uri_split()作为可读替代方案.

但我认为Regexp :: Common :: URI可能是HTTP URI语法验证的理想解决方案.

use Regexp::Common qw /URI/;
while (<>) {
    /$RE{URI}{HTTP}/  and  print "Contains an HTTP URI.\n";
}
Run Code Online (Sandbox Code Playgroud)

达米安写的任何东西都是由阿比盖尔维护的,无论是灵感,伟大,疯狂,还是以上所有.(我的意思是尽可能高的关注).