Perl - 使用正则表达式来匹配哈希键或值中的输入 [英] Perl - Using regex to match input in hash key or value

查看:282
本文介绍了Perl - 使用正则表达式来匹配哈希键或值中的输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,这是一项家庭作业。我正在使用正则表达式,我被困住了。



这是迄今为止我已经有用户指定一个文件名的代码,如果它存在,将名称的哈希填充为键,电话号码作为值。

 #!/ usr / bin / perl 

使用strict;

打印\\\
Enter文件名:;
我的$ file =< STDIN> ;;
chomp $ file;

如果(!open(我的$ fileName,&,$ file))
{
print对不起,该文件不存在! \\\
;
}
else
{
我的%phoneNums;
while(my $ line =< $ fileName>)
{
chomp($ line);
(我的$ name,我的$号)= split /:/,$ line;
$ phoneNums {$ name} = $ number;
}

打印读入文件!,\\\
\\\
;

打印输入搜索:;
my $ input =< STDIN> ;;
chomp $ input;

#HERE是我在哪里丢失
}

打印\\\
;

这是我被困的部分:



允许用户输入搜索字符串。
使用与手机相同的样式寻找匹配。搜索字符串中的任何个人
字符可以匹配
键中的任何其他字符,这意味着搜索字符串中的2可以匹配2,A,B或 C'在联系人列表中。匹配可以发生在联系人姓名或电话号码中。要发生匹配,搜索字符串中的每个字符必须按照联系人信息顺序显示,但不一定在每个
其他旁边。例如,搜索字符串86(与TM或NU的搜索字符串基本相同)将匹配TOM而不是主。
每个电话键上的字符:
0,
1,
2ABC,
3DEF,
4GHI,
5JKL,
6MNO,
7PQRS,
8TUV,
9WXYZ



我只是坚持如何使所有这些字符类,以及任何帮助在所有非常感激。

解决方案

解决方法是通过编写一个功能,将您的东西常见组件。执行此IMO的最佳方式是使用哈希:

 我的%num_to_letter =(
0 => ],
1 => [],
2 => [A,B,C],
3 => [D ,F],
4 => [G,H,I],
5 => [J,K,L ,
##等

);

我的%letter_to_num;
foreach my $ key(keys%num_to_letter){
foreach my $ element(@ {$ num_to_letter {$ key}}){
$ letter_to_num {lc($ element)} = lc $ key);
}
}
print Dumper \%letter_to_num;

这将创建一个映射到原始的字母或数字的地图 - 有点像这样: p>

  $ VAR1 = {
'b'=> '2',
'g'=> '4',
'e'=> '3',
'i'=> '4',
'a'=> '2',
'j'=> '5',
...

注意 - 你可以手动做,但是我喜欢从顶部的地图生成,因为我认为它看起来更整洁。注意 - 我们使用 lc 来降低所有内容,因此这样做不区分大小写。这可能值得关注 fc - 这是一个类似的工具,但处理国际字符。 (在此示例中与此不相关)



然后,您将搜索和目标都减少为其常用值:

  sub normalize {
my($ input)= @_;

#join没有分隔符。
return join('',
#look up $ _(每个字母)在$ letter_to_num
#if不存在,使用//运算符返回原始值
#this意味着我们可以将数字转成字母,
#,但将已经编号的数据保持不变
map {$ letter_to_num {lc($ _)} // $ _}
#split输入行为字符
split(//,$ input)
);
}

打印标准化(DAD),\\\
; ## 323

然后比较一个与另一个:

  my $ search =DAD; 
我的$ normalised_search = normalize($ search);
print搜索:\$ normalised_search\\\\
;

我的$ number_to_match ='00533932388';
我的$ string_to_match =daddyo;

打印匹配数\\
如果规范化($ number_to_match)=〜m / $ normalised_search /;
print匹配string\\\

如果normalize($ string_to_match)=〜m / $ normalised_search /;


First, this is a homework assignment. I am having a tough time with regex, and I'm stuck.

This is the code I have so far, where I have the user designate a filename, and if it exists, populates a hash of the names as keys, and the phone numbers as the values.

#!/usr/bin/perl

use strict;

print "\nEnter Filename: ";
my $file = <STDIN>;
chomp $file;

if(!open(my $fileName, "<", "$file"))
{
    print "Sorry, that file doesn't exist!", "\n";
}
else
{
    my %phoneNums;
    while (my $line=<$fileName>) 
    {
        chomp($line);
        (my $name,my $number) = split /:/, $line;
        $phoneNums{$name} = $number;
    }

    print "Read in the file!", "\n\n";

    print "Enter search: ";
    my $input = <STDIN>;
    chomp $input;

    #HERE IS WHERE I'M LOST
}

print "\n";

This is the part I am stuck on:

Allow the user to enter a search string. Look for matches using the same style as the phone. Any individual character in the search string can match any other character from the key, meaning a ‘2’ in the search string can match a ‘2’, ‘A’, ‘B’, or ‘C’ in the contact list. Matches can occur in the contact name or the phone number. For a match to occur, each character in the search string must appear, in order, in the contact info, but not necessarily next to each other. For example, a search string of "86" (essentially the same as a search string of "TM" or "NU") would match "TOM" but not "MOTHER". Characters on each phone keys: 0, 1, 2ABC, 3DEF, 4GHI, 5JKL, 6MNO, 7PQRS, 8TUV, 9WXYZ

I just am stuck on how exactly to make all those character classes, and any help at all is much appreciated.

解决方案

The way to tackle this is by writing a function that reduces your 'things' to their common components. The best way to do this IMO is use a hash:

my %num_to_letter = (
    0 => [],
    1 => [],
    2 => [ "A", "B", "C" ],
    3 => [ "D", "E", "F" ],
    4 => [ "G", "H", "I" ],
    5 => [ "J", "K", "L" ],
    ## etc.

);

my %letter_to_num;
foreach my $key ( keys %num_to_letter ) {
    foreach my $element ( @{$num_to_letter{$key}} ) { 
        $letter_to_num{lc($element)} = lc($key); 
    }
}
print Dumper \%letter_to_num;

This creates a map of which letters or numbers map to their original - a bit like this:

$VAR1 = {
          'b' => '2',
          'g' => '4',
          'e' => '3',
          'i' => '4',
          'a' => '2',
          'j' => '5',
...

Note - you can do this by hand, but I prefer to generate from the top map, because I think it looks neater. Note - we use lc to lower case everything, so this becomes case insensitive. It's probably worth looking at fc - which is a similar tool but handles international characters. (Not relevant in this example though)

You then 'reduce' both search and 'target' to their common values:

sub normalise {
    my ( $input ) = @_;

    #join with no delimiter. 
    return join ( '', 
             #look up $_ (each letter) in $letter_to_num
             #if not present, use // operator to return original value. 
             #this means we get to turn numbers into letters,
             #but leave things that are already numbers untouched. 
             map { $letter_to_num{lc($_)} // $_ } 
                  #split the input line into characters. 
                  split ( //, $input ) 
            );
}

print normalise ("DAD"),"\n";   ## 323

And then compare one against the other:

my $search            = "DAD";
my $normalised_search = normalise($search);
print "Searching for: \"$normalised_search\"\n";

my $number_to_match = '00533932388';
my $string_to_match = "daddyo";

print "Matches number\n"
    if normalise($number_to_match) =~ m/$normalised_search/;
print "Matches string\n"
    if normalise($string_to_match) =~ m/$normalised_search/;

这篇关于Perl - 使用正则表达式来匹配哈希键或值中的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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