我可以从一组哈希键构建Perl正则表达式吗? [英] Can I build a Perl Regex from a set of hash keys

查看:91
本文介绍了我可以从一组哈希键构建Perl正则表达式吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(与上一个问题相关:我需要重置一个Perl哈希索引?



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

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

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



例如,如果评论标题是

  cm1234  - 做一些CM工作

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

  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
}

但显然我想从散列键自己构建正则表达式(上面的散列例子会相当频繁地改变)。我想简单地按照以下方式简单地连接键:

 #构建正则表达式
my $ regex ='';
foreach我的$ key(键%project_keys){
$ regex + = $ key +'|';
}
$ regex = substr($ regex,0,-1); #斩掉最后一根烟管
$ regex ='('。$ regex。')(\d +)\s。*';
if($ title =〜/ $ regex /){
my $ url ='http://projects/'.$project_keys {$ 1}。'/ setter /'.$ 2
} b


但是a)它不能按我的意愿工作,b)我认为还有更好的方法Perl的方式来做到这一点。或者是有?

解决方案

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



我会建议:

  my $ project_match = join'|',map quotemeta,keys%project_keys; 

if($ title =〜/($ project_match)(\d +)\s /){
my $ url ='http://projects/'.$project_keys { 。$ 1}/设定器/'.$ 2;
#与$ url
}

quotemeta 是一个函数,用于转义字符串中出现的任何正则表达式元字符。在你的例子中没有任何东西,但总是使用它并避免意外的错误是一个很好的习惯。



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


(related to previous question: Do I need to reset a Perl hash index?)

I have a hash coming in from a file which is defined as follows:

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

I need to check whether a review title has the correct format, and if so, link to a separate URL.

For instance, if a review title is

"cm1234 - Do some CM work"

then I want to link to the following URL:

http://projects/customer_management/setter/1234

Currently, I'm using the following (hard-coded) regex:

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

but obviously I'd like to build the regex from the hash keys themselves (the hash example above will change fairly frequently). I thought about simply naively concatenating the keys as follows:

# 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
}

but a) it's not working as I would wish, and b) I assume there's a much better Perl way to do this. Or is there?

解决方案

Your main problem comes from trying to use + to join strings. It doesn't do that in Perl, the string concatenation operator is .. But a loop with string concatenation can often be done better with join instead.

I would suggest:

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 is a function that escapes any regex metacharacters that occur in a string. There aren't any in your example, but it's good practice to use it always and avoid unexpected bugs.

I left out the trailing .* in your pattern, because there's no need to say "and then some stuff, or maybe no stuff" if you don't actually do anything with the stuff. The pattern doesn't need to match the entire string, unless you anchor it to the beginning and end of the string.

这篇关于我可以从一组哈希键构建Perl正则表达式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆