问题描述
首先,这是一项家庭作业。我正在使用正则表达式,我被困住了。这是迄今为止我已经有用户指定一个文件名的代码,如果它存在,将名称的哈希填充为键,电话号码作为值。
#!/ 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
来降低所有内容,因此这样做不区分大小写。这可能值得关注 - 这是一个类似的工具,但处理国际字符。 (在此示例中与此不相关)
然后,您将搜索和目标都减少为其常用值:
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 individualcharacter in the search string can match any other character from thekey, 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 eachother. 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 - 使用正则表达式来匹配哈希键或值中的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!