需要明确的是,Perl 使用标量或它们的列表:
$scalar = 1;
@list = ( $scalar, $scalar, $scalar );
列表的每个项目都可以通过索引访问,例如$list[1].
您还可以按名称访问项目。这种结构称为哈希:$hash{ name1 }
%hash = ( 'name1', $scalar, 'name2', $scalar, 'name3', $scalar )
但是,如您所见,这仍然是一个列表。注意它周围的“()”。
再说一次,列表中的每一项只能是一个标量。
我没有在任何一本书中看到这一点,但$ 符号表示一个值,@ 表示值列表。
在此示例中,您有 一个值,因此您使用 $ 符号:
$scalar = $hash{ name1 };
$scalar = $list[ 1 ];
在下一个示例中,您有一个值列表,因此您使用“@”:
@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'
Perl 有引用。这是一个强大的工具。
$ref = \$scalar;
$ref = \@list;
$ref = \%hash;
$ref 也是标量,因为它只有一个值。要访问此$ref 引用的基础数据,您应该使用dereference。
$scalar = $$ref;
@list = @$ref;
%hash = %$ref;
但实际上,您并不想要整个列表或散列。你只想要其中的一些东西。为此,您可以使用-> 和 [] 告诉 Perl 你想访问一个列表元素,或者使用 {} 告诉 Perl 你想访问一个哈希元素:
$scalar = $ref->[ 1 ];
$scalar = $ref->{ name1 };
注意:您正在访问一个元素,因此您使用$ 符号。
如果您想要数组或散列中的元素列表,请使用@ 符号。例如:
@list = @$ref[ 1, 3..5 ];
@list = @$ref{ 'name1', 'name2' };
1st: $ref - 返回对结构的引用。 $ 表示您从变量 'ref' 中获得 一个 值
第二:@$ref - 你取消引用 $ref。 @ 表示您希望通过该引用访问 列表 项。
3rd-a:您从数组中获得 '1,3,4,5' 项(注意:[])
3rd-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;
=> - 只需引用左操作数并在其后加上,。
如果你想访问'hash2'的一个项:
$scalar = $hash2{ name1 };
$scalar = $href->{ name1 };
在取消引用后使用$href-> 将意味着%hash2。
如果您想访问两个或更多项“hash2”:
@list = @hash2{ 'name1', 'd' };
@list = @$href{ 'name1', 'd' };
在取消引用后使用@$href 将意味着%hash2
详细说明:
$scalar = $hash2{ name1 }; # <--- What does this mean???
$hash2 表示我们访问 %hash2 的 一个 项。这是对列表的引用:
$list_ref = $hash2{ name1 };
$scalar = $list_ref->[ 1 ]; # <--- what we get here???
$list_ref 表示我们访问一个项。 ->[ 表示我们访问该列表。因为$list_ref 指的是@list2,所以我们访问\%hash。我们可以一步完成:
$scalar = $hash2{ name1 }->[ 1 ];
当您将文本“$list_ref”替换为“$hash2{ name1 }”时,您可能会想到这里
我们说[ 1 ] 指的是%hash。因此,要访问该哈希的 一个 项,我们再次使用 $:
$hash_ref = $hash2{ name1 }->[ 1 ];
$scalar = $hash_ref->{ b };
$hash_ref 表示我们访问一个项。 ->{ 表示我们访问哈希。因为$hash_ref 指的是%hash,所以我们访问2。我们可以一步完成:
$scalar = $hash2{ name1 }->[ 1 ]->{ b };
当您将文本 '$hash_ref' 替换为 '$hash2{ name1 }->[ 1 ]' 时,您可能会再次想到这里。但是hash2 这里是%hash2。 $href 呢?请记住这个例子:
$scalar = $hash2{ name1 };
$scalar = $href->{ name1 };
您可能会注意到,如果您通过 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 };
-> 之后的括号类型将是 [ 用于数组或 { 用于哈希项。
$href 呢?
$scalar = $hash2{ name1 }->[ 1 ]->{ b };
$scalar = $href->{ name1 }->[ 1 ]->{ b };
在第一次取消引用之后,我们不需要->
$scalar = $hash2{ name1 }[ 1 ]{ b };
^-- first dereference
$scalar = $href->{ name1 }[ 1 ]{ b };
^--first dereference
回到您的问题:在 Perl 中,您可以将值的 LIST 传递给 subs 并返回一个 LIST。
sub test {
return @_;
}
在这里我们返回所有我们得到的物品。
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 ];
使用 $hashTable{$login} 可以,我应该使用 %hashTable{$login} 还是没关系?
不。您应该使用 $ 访问来自%hashTable 的一个 项。 $hashTable{$login} 是对的。
如果你想提取 两个 登录,你应该使用 @:
@list = @hashTable{ 'login1', 'login2' };
# or
$l1 = 'login1';
$l2 = 'login2';
@list = @hashTable{ $l1, $l2 };
返回 \$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!!!
)
所以authUser sub 会返回一个引用:
my $authHash = authUser( 'vasya' ); # & is not required at all
由于$authHash,如果引用是一个哈希,你应该使用->
if( $authHash->{ pass } eq $password ) {
...
}
但是,如果您的 authUser 是一个解析配置文件并返回所有用户,您应该将其重命名为 loadUsers 并返回一个 reference 到哈希:
子加载用户{
……
返回\%哈希表;
}
my $usersDB = loadUsers;
if( $usersDB->{ $login }->{ pass } eq $password ) {
print 'You have granged access';
}
else { ... }
编辑 2:任何人都可以修改我的代码以便我更好地理解答案吗?
不。阅读我的教程。要了解如何编写代码,您应该自己动手。
作为建议
当你是新手时:
-
总是使用 hashref 和 listref。
-
总是使用
-> 访问项目。
-
总是使用 $ 印记作为第一个字符。
.
$list = [ 1, 2, 3 ];
$hash = { a => 1, b => 2 };
$list->[ 2 ];
$hash->{ b };
当您访问整个数组或散列时例外:
@l = @$list;
%h = %$hash;
@l = keys %$hash;
@l = values %$hash;