Regex perl中哈希键的字符串比较

Regex perl中哈希键的字符串比较,regex,perl,hash,Regex,Perl,Hash,我在perl中有一个哈希映射,如下所示: MAP_MESSAGE_TO_NUMBER => { 'Hello World, I am XYZ' => 11, 'I am using Stack Overflow for Guidance' => 12, 'Programming is good!' => 13, }, 在我的Perl代码中,我试图使用哈希键进行匹配,如果匹配发生,我只返回相应的哈希值(数字) 我的代码运行良好 my

我在perl中有一个哈希映射,如下所示:

MAP_MESSAGE_TO_NUMBER => {
     'Hello World, I am XYZ'    => 11,
     'I am using Stack Overflow for Guidance'   => 12,
     'Programming is good!' => 13,
},
在我的Perl代码中,我试图使用哈希键进行匹配,如果匹配发生,我只返回相应的哈希值(数字)

我的代码运行良好

my $Strtomatch = 'Hello World, I am XYZ!';
if ( some condition ) {
    my $val =   MAP_MESSAGE_TO_NUMBER->{$Strtomatch};
    # some code will use the return value 
    doSomethingWith $val;  
}
我的问题是: 如果您将看到变量$stromatch的值有一个额外的字符“!”它不存在于原始哈希映射中。因此,我的哈希映射不会返回任何值

我的问题是如何使这个更通用,这样即使字符串的一部分匹配,我也可以进行比较

即使很少有字符与返回值的精细匹配

让我知道

我不确定如何在这里使用正则表达式,因为我正在对哈希映射中的值与来自其他函数的值进行比较。
我技术很好,编程不太好,尝试学习。

你可以使用
qr
类似引号的操作符在
=~
操作符之外编译正则表达式。这种方法的缺点是,现在您必须迭代搜索键以查看是否有任何模式匹配。它将比简单的散列查找慢得多

use constant MAP_MESSAGE_TO_NUMBER => (
  [qr/Hello World, I am XYZ/,                  11],
  [qr/I am using Stack Overflow for Guidance/, 12],
  [qr/Programming is good!/,                   13],
);

my $Strtomatch = 'Hello World, I am XYZ!';
if ($some_condition) {
  foreach my $map (MAP_MESSAGE_TO_NUMBER) {
    my ($pattern, $val) = @$map;
    if ($Strtomatch =~ $pattern) {
      # some code will use the return value 
      doSomethingWith $val;
      # optionally exit the loop at this point with `last`, or store multiple match results 
    }
  }
  # optionally check if any match was found and print an error if not
}

我们不能使用散列作为主数据结构,因为我们的正则表达式将成为无lessed的,所以我在这里使用了一个数组数组。如果您想使用散列,可以查看Tie::RegepHash和/或Tie::hash::Regex。

您可以使用
qr
类引号运算符在
=~
运算符之外编译正则表达式。这种方法的缺点是,现在您必须迭代搜索键以查看是否有任何模式匹配。它将比简单的散列查找慢得多

use constant MAP_MESSAGE_TO_NUMBER => (
  [qr/Hello World, I am XYZ/,                  11],
  [qr/I am using Stack Overflow for Guidance/, 12],
  [qr/Programming is good!/,                   13],
);

my $Strtomatch = 'Hello World, I am XYZ!';
if ($some_condition) {
  foreach my $map (MAP_MESSAGE_TO_NUMBER) {
    my ($pattern, $val) = @$map;
    if ($Strtomatch =~ $pattern) {
      # some code will use the return value 
      doSomethingWith $val;
      # optionally exit the loop at this point with `last`, or store multiple match results 
    }
  }
  # optionally check if any match was found and print an error if not
}

我们不能使用散列作为主数据结构,因为我们的正则表达式将成为无lessed的,所以我在这里使用了一个数组数组。如果要使用散列,可以查看Tie::RegepHash和/或Tie::hash::Regex。

以下是一种方法:

#!/usr/bin/env perl
use strict;
use warnings;

my %msg_to_number = ( 
     'Hello World, I am XYZ'    => 11,
     'I am using Stack Overflow for Guidance'   => 12,
     'Programming is good!' => 13,
);

my $str_to_match = 'Hello World, I am XYZ!';
#note - grep returns a list. We chuck any duplicate hits away. 
my ( $first_match ) = grep { $str_to_match =~ m/\Q$_\E/ } keys %msg_to_number;

print "$first_match   =  $msg_to_number{$first_match}\n";
注意-grep中的模式匹配是反向的。检查字符串是否与哈希中的键匹配,如果匹配,则返回该值。只有当您的键是主字符串的子字符串(或完全匹配)时,它才起作用

而且它只得到一个“第一”匹配,所以实际上,如果有重复,结果将是随机的。因此,请确保您的哈希键足够唯一

例如:

将随机提供以下信息:

Programming is good!   =  13
Hello World, I am XYZ   =  11
另一种方法是,对输入/输出执行公共转换,这使得它对差异“视而不见”

例如

这将剥离
\W
,它是“非单词”字符(如标点符号和空格),并将两者进行类似的比较。这意味着您的匹配有点模糊,并且允许使用任意感叹号、空格等

如果你想处理一个默认情况,那么这个方法非常方便<代码>/运算符就是您想要的

return $msg_to_number{$first_match} // "default value here " ;
(或者您可以只测试
$first\u match
上定义的内容)


对于不区分大小写的匹配,正则表达式的
i
修饰符将执行第二个示例中的技巧

这里有一种方法可以做到:

#!/usr/bin/env perl
use strict;
use warnings;

my %msg_to_number = ( 
     'Hello World, I am XYZ'    => 11,
     'I am using Stack Overflow for Guidance'   => 12,
     'Programming is good!' => 13,
);

my $str_to_match = 'Hello World, I am XYZ!';
#note - grep returns a list. We chuck any duplicate hits away. 
my ( $first_match ) = grep { $str_to_match =~ m/\Q$_\E/ } keys %msg_to_number;

print "$first_match   =  $msg_to_number{$first_match}\n";
注意-grep中的模式匹配是反向的。检查字符串是否与哈希中的键匹配,如果匹配,则返回该值。只有当您的键是主字符串的子字符串(或完全匹配)时,它才起作用

而且它只得到一个“第一”匹配,所以实际上,如果有重复,结果将是随机的。因此,请确保您的哈希键足够唯一

例如:

将随机提供以下信息:

Programming is good!   =  13
Hello World, I am XYZ   =  11
另一种方法是,对输入/输出执行公共转换,这使得它对差异“视而不见”

例如

这将剥离
\W
,它是“非单词”字符(如标点符号和空格),并将两者进行类似的比较。这意味着您的匹配有点模糊,并且允许使用任意感叹号、空格等

如果你想处理一个默认情况,那么这个方法非常方便<代码>/运算符就是您想要的

return $msg_to_number{$first_match} // "default value here " ;
(或者您可以只测试
$first\u match
上定义的内容)


对于不区分大小写的匹配,正则表达式的
i
修饰符将执行第二个示例中的技巧

这可以通过迭代散列中的所有键并保持最接近的匹配来解决。如果您的哈希非常大或性能非常关键,这可能不是一个可行的选择。您的想法至少在理论上是有问题的,因为返回值可能不再是标量,因为可能有多个键匹配
$strotmatch
。当然你可以选择你找到的第一个,如果这是你想要的。。。。但是,当谈到散列时,“第一个”是什么?在这种情况下,最好使用两个序列:第一个带键的序列,第二个带值的序列。或者一个由两个元素组成的数组。我认为你必须重新考虑你的策略。哈希查找用于精确匹配,而查找部分匹配并不实用。你必须提供更多的细节,说明什么样的部分匹配对任何人来说都是可以帮助你的。这可以通过迭代散列中的所有键并保持最接近的匹配来解决。如果您的哈希非常大或性能非常关键,这可能不是一个可行的选择。您的想法至少在理论上是有问题的,因为返回值可能不再是标量,因为可能有多个键匹配
$strotmatch
。当然你可以选择你找到的第一个,如果这是你想要的。。。。但是,当谈到散列时,“第一个”是什么?在这种情况下,最好使用两个序列:第一个带键的序列,第二个带值的序列。或者一个由两个元素组成的数组。我认为你必须重新考虑你的策略。哈希查找用于精确匹配,而查找部分匹配并不实用。你必须给出更多的细节,说明什么样的部分匹配适合任何人