【问题标题】:Can I build a Perl Regex from a set of hash keys我可以从一组哈希键中构建一个 Perl 正则表达式吗
【发布时间】:2014-04-16 00:13:10
【问题描述】:

(与上一题相关:Do I need to reset a Perl hash index?

我有一个来自文件的哈希值,定义如下:

%project_keys = (
    cd     => "continuous_delivery",
    cm     => "customer_management",
    dem    => "demand",
    dis    => "dis",
    do     => "devops",
    sel    => "selection",
    seo    => "seo"
);

我需要检查评论标题的格式是否正确,如果是,请链接到单独的 URL。

例如,如果评论标题是

"cm1234 - Do some CM work"

然后我想链接到以下网址:

http://projects/customer_management/setter/1234

目前,我正在使用以下(硬编码)正则表达式:

if ($title =~ /(cd|cm|dem|dis|do|sel|seo)(\d+)\s.*/) {
    my $url = 'http://projects/'.$project_keys{$1}.'/setter/'.$2
}

但显然我想从哈希键本身构建正则表达式(上面的哈希示例会经常更改)。我想过简单地将键连接如下:

# Build the regex
my $regex = '';
foreach my $key ( keys %project_keys ) {
    $regex += $key + '|';
}
$regex = substr($regex, 0, -1); # Chop off the last pipe
$regex = '('.$regex.')(\d+)\s.*';
if ($title =~ /$regex/) {
    my $url = 'http://projects/'.$project_keys{$1}.'/setter/'.$2
}

但是 a) 它没有像我希望的那样工作,并且 b) 我认为有更好的 Perl 方法可以做到这一点。或者有吗?

【问题讨论】:

    标签: regex perl hash


    【解决方案1】:

    您的主要问题来自尝试使用+ 连接字符串。在 Perl 中并没有这样做,字符串连接运算符是 .。但是使用join 代替通常可以更好地完成字符串连接的循环。

    我建议:

    my $project_match = join '|', map quotemeta, keys %project_keys;
    
    if ($title =~ /($project_match)(\d+)\s/) {
       my $url = 'http://projects/'.$project_keys{$1}.'/setter/'.$2;
       # Something with $url
    }
    

    quotemeta 是一个转义字符串中出现的任何正则表达式元字符的函数。您的示例中没有任何内容,但最好始终使用它并避免意外错误。

    我在你的模式中省略了尾随的.*,因为如果你实际上没有对这些东西做任何事情,就没有必要说“然后是一些东西,或者可能没有东西”。该模式不需要匹配 整个 字符串,除非您将其锚定到字符串的开头和结尾。

    【讨论】:

    • 太棒了。只是……太棒了。
    • 如果我正确阅读了文档,它可以在没有正则表达式中 $project_match 周围的括号的情况下工作 - 我认为它存在所以我可以在后续字符串中使用 $1 是否正确?
    • @roryhewitt 不,如果没有第一组括号,那么$1 将是 ID,$2 将不会被设置。
    猜你喜欢
    • 1970-01-01
    • 2011-07-08
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    相关资源
    最近更新 更多