【问题标题】:Perl Regex to Exclude Certain TLDs for SpamassassinPerl 正则表达式为 Spamassassin 排除某些 TLD
【发布时间】:2015-06-26 03:47:38
【问题描述】:

完全不能用 Perl 编写代码;所以,看起来很简单的事情——编写一个正则表达式来为所有 not 的“com”或“net”或“org”TLD 的 URI 评分——显然超出了我的技能范围。有没有好心人赐教?

例如,我希望 https://foo.com.us/asdf?qwerty=123 匹配,而 ftp://madeup.kernel.org/path/to/some/tarball.tar.bz2 不匹配。

【问题讨论】:

    标签: regex perl uri tld spamassassin


    【解决方案1】:

    正则表达式模式

    //(?:[a-z]+\.)*+(?!com/|net/|org/)
    

    应该做你想做的。斜线是模式的一部分,不是分隔符

    这是一个演示

    use strict;
    use warnings;
    use 5.010;
    
    my @urls = qw{
        https://foo.com.us/asdf?qwerty=123
        ftp://madeup.kernel.org/path/to/some/tarball.tar.bz2
    };
    
    for ( @urls ) {
        say m{//(?:[a-z]+\.)*+(?!com/|net/|org/)} ? 'match' : 'no match';
    }
    

    输出

    match
    no match
    

    【讨论】:

    • 我试过 ...(?!com|net|org)\/ 没有成功。 [虽然错字失败是可能的。 :)] 在“或”组中包含最后的斜线是否有理由?
    • @justinzane:如果没有斜线,正则表达式将拒绝 TLD 开头的任何这些字符串的名称。例如,www.batman.comics 将无法通过测试。实际上我已经重写了一点,这样 URL 就不必有路径了
    • 很好地使用possessive greed!请注意,URL 可能没有路径,或者可能有端口或查询而不是路径。我建议否定前瞻为(?!(?:com|net|org)\b(?![.-])),其中包括一个双重否定,以避免出现主机名中允许的字符后出现断字。此外,字符类应为 [\w-] 以允许使用数字和破折号。
    【解决方案2】:

    您应该使用 URI 模块将主机名与 URL 的其余部分分开

    此示例仅提取主机名的最后一个子字符串,因此它会从bbc.co.uk 中查找uk,但它应该符合您的目的

    use strict;
    use warnings;
    
    use URI;
    
    my @urls = qw{
        https://foo.com.us/asdf?qwerty=123
        ftp://madeup.kernel.org/path/to/some/tarball.tar.bz2
    };
    
    for my $url ( @urls ) {
        $url = URI->new($url);
        my $host = $url->host;
        my ($tld) = $host =~ /([^.]+)\z/;
    
        if ( $tld !~ /^(?com|net|org)\z/ ) {
            # non-standard TLD
        }
    }
    

    【讨论】:

    • 因为这是一个 Spamassassin local.cf 规则,我需要一个基本的 Perl 正则表达式而不加载任何其他模块。我认为原因是正则表达式必须经过 re2c 处理并编译为“spamd”后才能使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2017-10-02
    • 1970-01-01
    • 2013-10-31
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多