the*_*wrp 5 arrays perl hash subroutine
我已经尝试了几个小时的例子,但我似乎无法掌握如何做我想做的事情.
我想从子例程返回一个哈希,我认为引用是最好的选择.这里有点棘手.我想引用像$ hash {$ x}这样的哈希.我仍然是perl的菜鸟:/
1.第一个问题,我使用的例子似乎表明可以使用$ hashTable {$ login},我应该使用%hashTable {$ login}还是没关系?以下是代码:
sub authUser {
$LocalPath = "/root/UserData";
open(DATAFILE, "< $LocalPath");
while( $linebuf = <DATAFILE> ) {
chomp($linebuf);
my @arr = split(/:/, $linebuf);
my $login = $arr[1]; # arr[1] contains the user login names
my $hashTable{ $login } = "$arr[0]"; #$arr[0] is account number
}
close DATAFILE;
return \$hashTable{ $login };
}
Run Code Online (Sandbox Code Playgroud)
然后我想测试这些数据以查看是否存在登录,这是我的测试方法
# test login Dr. Brule which is present in UserData
my $test = "Dr. Brule";
my $authHash = &authUser();
if ( $authHash{ $test } ) {
print "Match for user $test";
}
else {
print "No Match for user $test";
}
Run Code Online (Sandbox Code Playgroud)
2.我的$ authHash应该是$ authHash {$ something},我对此非常困惑
编辑:经过一些阅读提示,仍然尝试但没有骰子,任何帮助将不胜感激
首先,正如评论中提到的mpapec use strict; use warnings;.这将抓住最常见的错误,包括标记您在此处询问的大部分问题(通常会提供有关您应该做什么的提示).
现在回答问题1和2:
%hash哈希是一个整体.完整的数据结构.
$hash{key} 是哈希中的单个元素.
因此,\%hash是%hash对整个哈希的引用,在这种情况下,它似乎是您打算返回的内容. \$hash{key}是对单个元素的引用.
在第二个问题中,它变得棘手的是引用总是标量,无论它们指的是什么.
$hash_ref = \%hash
要从您引用的哈希中获取元素,您需要首先取消引用它.这通常由->运营商完成,如下所示:
$hash_ref->{key}
请注意,->从reference($hash_ref->{key})开始时使用,但从实际hash($hash{key})开始时不使用.
(作为问题2的旁注,请不要使用&- 只需使用authUser()而不是&authUser().使用&Perl 5+中不再需要.并且具有您通常不想要的副作用,因此您不应该习惯在不需要的地方使用它.)
对于问题3,如果你只想检查一次,你也可以循环遍历数组并检查每个元素:
my $valid;
for my $username (@list_of_users) {
if ($login eq $username) {
$valid = 1;
last; # end the loop since we found what we're looking for
}
}
if ($valid) {
print "Found valid username $login\n";
} else {
print "Invalid user! $login does not exist!\n";
}
Run Code Online (Sandbox Code Playgroud)
需要明确的是,Perl 使用标量或标量列表:
$scalar = 1;
@list = ( $scalar, $scalar, $scalar );
Run Code Online (Sandbox Code Playgroud)
列表的每一项都可以通过索引访问,例如$list[1]。
您还可以按名称访问项目。这种结构称为散列:$hash{ name1 }
%hash = ( 'name1', $scalar, 'name2', $scalar, 'name3', $scalar )
Run Code Online (Sandbox Code Playgroud)
但是,正如您所看到的,这仍然是一个列表。注意()它周围的“ ”。
同样,列表中的每一项都只能是一个 scalar。
我没有任何书看到了这一点,但该$标志意味着一个值,@手段值列表。
在本例中,您有一个 value,因此您使用$符号:
$scalar = $hash{ name1 };
$scalar = $list[ 1 ];
Run Code Online (Sandbox Code Playgroud)
在下一个示例中,您有一个值列表,因此您使用“ @ ”:
@list2 = @list1; # copy all items
@list2 = @list[ 1, 3..5 ]; # copy four items with index 1,3,4,5
@list2 = @hash{ 'name1', 'name3' }; #copy two items with index 'name1', 'name2'
Run Code Online (Sandbox Code Playgroud)
Perl 有参考。这是一个强大的工具。
$ref = \$scalar;
$ref = \@list;
$ref = \%hash;
Run Code Online (Sandbox Code Playgroud)
$ref也是标量,因为它只有一个值。要访问 this引用的基础数据$ref,您应该使用取消引用。
$scalar = $$ref;
@list = @$ref;
%hash = %$ref;
Run Code Online (Sandbox Code Playgroud)
但实际上,您不想要整个列表或散列。你只想要其中的一些项目。为此,您可以使用->and[]告诉 Perl 您想要访问一个列表元素,或者{}告诉 Perl 您想要访问一个散列元素:
$scalar = $ref->[ 1 ];
$scalar = $ref->{ name1 };
Run Code Online (Sandbox Code Playgroud)
注意:您正在访问一个元素,因此您使用了$符号。
如果您想要数组或散列中的元素列表,请使用@符号。例如:
@list = @$ref[ 1, 3..5 ];
@list = @$ref{ 'name1', 'name2' };
Run Code Online (Sandbox Code Playgroud)
第一个:$ref - 返回对结构的引用。$表示您从变量 'ref'
2nd 中获得一个值
:@$ref - 您取消引用 $ref。@表示您想通过该引用访问项目列表。
3-A:你从数组'1,3,4,5'项目(注意:[])
3-B:你得到'NAME1', 'NAME2'项目从哈希(注意:{})
但是,当您获得对哈希或列表的引用并将此引用置于另一个哈希或数组时,我们可能会创建复杂的结构,例如哈希的哈希数组或哈希数组的哈希。例子:
@list = ( 1, 2, 3, 4, 5 );
%hash = ( 'a', 1, b => 2 );
@list2 = ( \@list, \%hash, 3, 'y' );
%hash2 = ( name1 => \@list2, d => 4 );
%hash2 = ( 'name1', \@list2, 'd', 4 ); #same. no any difference.
$href = \%hash2;
Run Code Online (Sandbox Code Playgroud)
=>- 只需引用左操作数并放在,它之后。
如果你想获得一个“HASH2”的项目:
$scalar = $hash2{ name1 };
$scalar = $href->{ name1 };
Run Code Online (Sandbox Code Playgroud)
$href->在取消引用后使用将意味着%hash2.
如果您想访问两个或多个'hash2' 项目:
@list = @hash2{ 'name1', 'd' };
@list = @$href{ 'name1', 'd' };
Run Code Online (Sandbox Code Playgroud)
@$href在取消引用后使用将意味着%hash2
详细信息:
$scalar = $hash2{ name1 }; # <--- What does this mean???
Run Code Online (Sandbox Code Playgroud)
$hash2意味着我们进入一个%HASH2的项目。这是对列表的引用:
$list_ref = $hash2{ name1 };
$scalar = $list_ref->[ 1 ]; # <--- what we get here???
Run Code Online (Sandbox Code Playgroud)
$list_ref意味着我们访问一个项目。->[意味着我们访问列表。因为$list_ref是指@list2,我们访问\%hash。我们可以一步完成:
$scalar = $hash2{ name1 }->[ 1 ];
Run Code Online (Sandbox Code Playgroud)
当您将文本 '$list_ref' 替换为 '$hash2{ name1 }' 时,您可能会想到这里
我们说是[ 1 ]指%hash。因此,要访问该哈希的一项,我们再次使用$:
$hash_ref = $hash2{ name1 }->[ 1 ];
$scalar = $hash_ref->{ b };
Run Code Online (Sandbox Code Playgroud)
$hash_ref意味着我们访问一个项目。->{意味着我们访问哈希。因为$hash_ref是指%hash我们访问2。我们可以一步完成:
$scalar = $hash2{ name1 }->[ 1 ]->{ b };
Run Code Online (Sandbox Code Playgroud)
当您将文本 '$hash_ref' 替换为 '$hash2{ name1 }->[ 1 ]' 时,您可能会再次想到这里。但hash2这里是%hash2。怎么样$href?请记住这个例子:
$scalar = $hash2{ name1 };
$scalar = $href->{ name1 };
Run Code Online (Sandbox Code Playgroud)
您可能会注意到,如果您通过 ref 访问该项目,您只需添加->. 相比:
@l = ( 1, 2, 3, 4 );
$scalar = $l[ 1 ]; # to access to second item of @l list
$hr = \@l;
$scalar = $hl->[ 1 ]; # to access to second item of @l list
%h = @l;
$scalar = $h{ 1 };
$hr = \%h;
$scalar = $hr->{ 1 };
Run Code Online (Sandbox Code Playgroud)
后面的括号类型->将[用于数组或{哈希项。
怎么样$href?
$scalar = $hash2{ name1 }->[ 1 ]->{ b };
$scalar = $href->{ name1 }->[ 1 ]->{ b };
Run Code Online (Sandbox Code Playgroud)
在第一次取消引用之后,我们不需要 ->
$scalar = $hash2{ name1 }[ 1 ]{ b };
^-- first dereference
$scalar = $href->{ name1 }[ 1 ]{ b };
^--first dereference
Run Code Online (Sandbox Code Playgroud)
回到您的问题:在 Perl 中,您可以将值列表传递给 subs 并返回一个列表。
sub test {
return @_;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们返回我们获得的所有项目。
return \%hash; # fn()->{ name1 }; # actually all these is list of one item
return \@list; # fn()->[ 1 ]; # so we may write: (fn())[0]->[ 1 ];
return $scalar; # fn(); # here also list of one item
return ( $scalar, \%hash, \@list );
(fn())[ 0 ];
(fn())[ 1 ]->{ name1 };
(fn())[ 2 ]->[ 1 ];
Run Code Online (Sandbox Code Playgroud)
可以使用 $hashTable{$login},我应该使用 %hashTable{$login} 还是没关系?
不。您应该使用$来访问一个从项目%hashTable。$hashTable{$login}是对的。
如果要提取两个登录名,则应使用@:
@list = @hashTable{ 'login1', 'login2' };
# or
$l1 = 'login1';
$l2 = 'login2';
@list = @hashTable{ $l1, $l2 };
Run Code Online (Sandbox Code Playgroud)
返回 \$hashTable{ $login };
错误的。您从散列中返回一项。所以return $hashTable{ $login }是对的。
2.如果我的 $authHash 真的是 $authHash{ $something },我对此很困惑
我想你%hashTable是一个由 $login 键控的哈希列表。像这样:
$login1 = { name => 'Vasiliy', pass => 'secret' } # ref to hash
%login2 = ( name => 'Petrovich', pass => '^&UDHJ' ); # just a hash
%hashTable = (
vasya => $login1, # items are always refs!!!
piter => \%login2, # items are always refs!!!
)
Run Code Online (Sandbox Code Playgroud)
所以authUsersub 将返回一个引用:
my $authHash = authUser( 'vasya' ); # & is not required at all
Run Code Online (Sandbox Code Playgroud)
由于 $authHash,如果引用是一个哈希,你应该使用 ->
if( $authHash->{ pass } eq $password ) {
...
}
Run Code Online (Sandbox Code Playgroud)
但是如果你authUser是一个解析配置文件并返回所有用户,你应该将它重命名为loadUsers并返回对哈希的引用: sub loadUsers { .... return \%hashTable; }
my $usersDB = loadUsers;
if( $usersDB->{ $login }->{ pass } eq $password ) {
print 'You have granged access';
}
else { ... }
Run Code Online (Sandbox Code Playgroud)
编辑 2:任何人都可以修改我的代码以便我可以更好地理解答案吗?
不。阅读我的教程。要了解如何编写代码,您应该自己动手。
作为建议
当您是新手时:
->访问项目。 .
$list = [ 1, 2, 3 ];
$hash = { a => 1, b => 2 };
$list->[ 2 ];
$hash->{ b };
Run Code Online (Sandbox Code Playgroud)
访问整个数组或散列时会出现异常:
@l = @$list;
%h = %$hash;
@l = keys %$hash;
@l = values %$hash;
Run Code Online (Sandbox Code Playgroud)