perl引用的相关知识分享_perl

为何使用引用?

在perl4中,hash表中的value字段只能是scalar,而不能是list,这对于有些情况是很不方便的,比如有下面的数据:
Chicago, USA
Frankfurt, Germany
Berlin, Germany
Washington, USA
Helsinki, Finland
New York, USA

我们想要按国家将城市分类,每个国家后面对应城市列表,如果用perl4来做,必须将城市列表组合成字符串才行,如果用perl5就可以用引用来做,有了引用,就可以构造复杂的hash结构,就可以用列表作为hash的值了。

如何定义引用

方法一 使用斜线\

定义变量的时候,在变量名前面加个\,就得到了这个变量的一个引用,比如

复制代码 代码如下:

# 数组的引用
my@array= (1,2,3) ;
my$aref=\@array ;
#哈希的引用
my%hash= ("name"=>"zdd","age"=>30,"gender"=>"male") ;
my$href=\%hash ;
#标量的引用
my$scalar=1 ;
my$sref=\$scalar ;

方法二 匿名引用

方法一不是很常用,最常用的还是匿名引用,方法如下
匿名数组引用-用[]定义
$aref= [ 1,"foo",undef,13 ];

匿名数组的元素仍然可以是匿名数组,所以我们可以用这种方法构造数组的数组,可以构造任意维度的数组。
my $aref = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
]

匿名哈希引用-用{}定义

$href= { APR =>4, AUG =>8 };

使用引用

定义了引用之后,可以使用不同的方法来访问引用,这里主要有三种方法。记忆这三种方法有个诀窍,将他们与普通的变量访问作比较即可。

方法一

与普通变量的访问方法相比,假设原来的变量名是name,则此方法在所有name出现的地方用$name代替,如下:

复制代码 代码如下:

my $scalar = 1 ;
my @array = (1, 2, 3) ;
my %hash = ('zdd' => 30, 'autumn' => 27) ;
my $sref = \$scalar ;   # scalar reference
my $aref = \@array ;    # array reference
my $href = \%hash ;     # hash reference

# 方法一

复制代码 代码如下:

print $$sref, "\n" ;  # 用$sref代替sref
print @$aref, "\n" ;   # 用$aref代替aref
print %$href, "\n" ;   # 用$href代替href
print $$aref[2], "\n" ;
print $$href{'zdd'}, "\n" ;

#方法二

复制代码 代码如下:

#与普通变量的访问方法相比,假设变量原来的名字是name,则现在用{$name}来代替name。
@a        @{$aref}         An array
   reverse@a  reverse @{$aref}    Reverse the array
   $a[3]      ${$aref}[3]       An element of the array
   $a[3] =17;   ${$aref}[3] =17    Assigning an element

#同理,哈希引用的使用方法如下。

复制代码 代码如下:

%h          %{$href}           A hash
   keys%h      keys%{$href}        Get the keys from the hash
   $h{'red'}      ${$href}{'red'}       An element of the hash
   $h{'red'} =17   ${$href}{'red'} =17    Assigning an element

注意:当{}内部是$var的形式时,{}是可以省略的,也就是说@{$aref}等价于@$aref,不过初学最好养成使用{}的习惯。

方法三
前两种方法比较繁琐,这种很简洁,就是使用箭头符号->

复制代码 代码如下:

$aref->[]  数组解引用
$href->{}  哈希解引用
$href->()  子过程解引用
$aref->[0] =3 ;
$href->{name} ="autumn" ;
$sref=2 ;
也可以将引用赋值给其他变量
my$aref1=$aref ;
my$href1=$href ;
my$scalar1=$scalar ;

解引用总结

复制代码 代码如下:

my $scalar = 1 ;
my @array = (1, 2, 3) ;
my %hash = ('zdd' => 30, 'autumn' => 27) ;
my $sref = \$scalar ;   # scalar reference
my $aref = \@array ;    # array reference
my $href = \%hash ;     # hash reference
# 方法一
print $$sref, "\n" ;
print @$aref, "\n" ;
print %$href, "\n" ;
print $$aref[2], "\n" ;
print $$href{'zdd'}, "\n" ;
# 方法二
print ${$sref}, "\n" ;
print @{$aref}, "\n" ;
print %{$href}, "\n" ;
print ${$aref}[2], "\n" ;
print ${$href}{'zdd'}, "\n" ;
# 方法三,不适用于标量
print $aref->[0], "\n" ;
print $href->{'zdd'}, "\n" ;
数组的数组
@a = (
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
)

我们知道[1, 2, 3]定义了一个(1, 2, 3)的匿名引用,所以数组a实际上包含三个元素,每个元素是一个引用,该引用指向一个数组,所以我们可以用下面的方法来访问数组元素(注意,下标从0开始)

$a[1][2]表示第二行第三列元素6,也可以写成$a[1]->[2],不过很少有人这么写。还可以写成${$a[1]}[2],几乎没人这么写!

多维数组的另一个写法如下:

复制代码 代码如下:

my $aref = [1, [2, 3], [4, 5, 6]] ;
print $aref->[0] , "\n" ; #1
print $aref->[1][1], "\n" ; #3
print $aref->[2][0], "\n" ; #4

这两者的区别有以下几点:
1)、前者是真正的数组,所以定义变量是使用@,后者是指向匿名数组的引用,所以定义的时候使用$
2)、前者的数组元素是匿名数组,而外层数组则是实体数组,后者无论元素还是外层数组都是匿名数组
3)、前者可以用$a[x][y]的形式访问,而后者只能用解引用的方式访问,即$a->[x][y]的形式。

数组的哈希,哈希的数组,哈希的哈希

也就是哈希表中的每个元素也是一个哈希表,比如一个学生集合组成的哈希,其key是学生名字(唯一),其值是每个学生的属性,比如年龄,身高及学号等。

复制代码 代码如下:

my $student_properties_of = {
    'zdd' => {
        'age' => 30,
        'hight' => 170,
        'id' => '001',
    },
    'autumn' => {
        'age' => 27,
        'hight' => 165,
        'id' => '002',
    }
} ;

引用的赋值

$aref2 = $aref1; 将使得$aref2和$aref1指向同一个数组,如果想将$aref1指向的数组拷贝一份给$aref2的话,使用下面的方法,[]里面对数组进行解引用,而[]以解引用后的数组为内容生成了一个新的匿名数组,又赋值给$aref2。
$aref2 = [@{$aref1}];

注意:不能使用下面的形式,外层的[]是不可缺少的。由于=左边是标量,所以右边的数组会被解释为标量环境,得到的是数组元素个数,而不是元素本身。但是如果加上[]就可以了,这样perl知道这是一个匿名数组的赋值。
$aref2 = @{$aref1};

判断一个变量是否是引用

使用ref函数即可,如果变量是引用则返回真,否则返回假。实际上它更智能,它会返回引用对应的类型,比如HASH或者ARRAY。

复制代码 代码如下:

my $aref1 = [1, 2, 0] ;
print ref $aref1, "\n" ; #输出 ARRAY
if (ref $aref1) {
    print "true\n" ; #输出 true
}

判断两个引用是否指向同一个目标

可以用eq,这将以字符串的形式判断,也可以使用==

复制代码 代码如下:

my $aref1 = [1, 2, 0] ;
my $aref2 = $aref1 ;
print $aref1, "\n" ;
print $aref2, "\n" ;
if ($aref1 eq $aref2) {
    print "reference equal\n" ;
}
if($aref1 == $aref2) {
    print "reference equal\n" ;
}

产生如下输出:
ARRAY(0x248bec)
ARRAY(0x248bec)
reference equal (eq)
reference equal (==)

时间: 2024-07-31 12:57:22

perl引用的相关知识分享_perl的相关文章

perl 调试命令的相关知识小结_perl

缺省的Perl调试器就是perl解释器本身,另外还有图形界面的调试器.由于在开发程序时一般都使用telnet访问服务器,因此本文主要为大家介绍下缺省的命令行调试器的用法. 用-d命令行选项启动Perl解释器,例如:perl-dtest.pl即进入Perl调试器的交互界面. 调试命令列表:(所有命令都在调试提示符下顶格输入,命令大小写有关)h:显示调试器的帮助信息.|h:以分页形式显示调试器的帮助信息.hh:显示一个压缩的帮助信息.h调试命令:显示某个调试命令的帮助. Perl调试器用法中p表达式

7个perl数组高级操作技巧分享_perl

1.去除一个数组中的重复元素: 使用grep函数代码片段: 代码: 复制代码 代码如下: my @array = ( 'a', 'b', 'c', 'a', 'd', 1, 2, 5, 1, 5 ); my %count; my @uniq_times = grep { ++$count{ $_ } < 2; } @array; 使用转换hash代码片段: 代码: 复制代码 代码如下: my @array = ( 'a', 'b', 'c', 'a', 'd', 1, 2, 5, 1, 5 );

C++中对象的常引用、动态建立和释放相关知识讲解_C 语言

C++对象的常引用 我们知道,一个变量的引用就是变量的别名.实质上,变量名和引用名都指向同一段内存单元. 如果形参为变量的引用名,实参为变量名,则在调用函数进行虚实结合时,并不是为形参另外开辟一个存储空间(常称为建立实参的一个拷贝), 而是把实参变量的地址传给形参(引用名),这样引用名也指向实参变量. [例] 对象的常引用. #include <iostream> using namespace std; class Time { public: Time(int,int,int); int

perl 采集入库脚本分享_perl

#!/usr/bin/perl -w use DBI; use POSIX qw(strftime); my $dbh = DBI->connect("DBI:mysql:shencan:111.1.32.153:3306″,"shencan","shencan"); #my $sql = "select * from shencan.LVS"; #my $sth = $dbh->prepare($sql); #$sth-&

十进制负数转换为二进制、八进制、十六进制的知识分享_相关技巧

程序猿们或许对二进制都不陌生,二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.但是很多人都会将二进制转换成整数,但是如何用二进制表示负数呢?有的人会说,在二进制前面加个负数符合.而计算机只能认识0 和 1,又怎么去加个额外的负数符号呢?于是我们就需要用0和1来表示负数.如果想要弄懂这个,我们需要先了解什么是二进制原码. 原码是什么 原码(true form)是一种计算机中对数字的二进制定点表示方法.原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为

javascript基础知识分享之类与函数化_基础知识

1.对象适合于收集和管理数据,容易形成树型结构. Javascript包括一个原型链特性,允许对象继承另一对象的属性.正确的使用它能减少对象的初始化时间和内存消耗. 2.函数它们是javascript的基础模块单元,用于代码复用.信息隐藏和组合调用.函数用于指定对象的行为.一般来说,编程就是将一组需求分解成一组函数和数据结构的技能. 3.模块我们可以使用函数和闭包来构造模块.模块是一个提供接口却隐藏实现状态和实现的函数或对象. 1.自定义类型--构造函数模式(伪类模式) 在基于类的系统中,对象是

讲解Python中面向对象编程的相关知识

  这篇文章主要介绍了深入讲解Python中面向对象编程的相关知识,是Python入门学习中的基础知识,需要的朋友可以参考下 Python从第一天开始就是面向对象的语言.正因为如此,创建和使用类和对象是非常地容易.本章将帮助您在使用Python面向对象编程的技术方面所有提高. 如果没有任何以往面向对象(OO)的编程的经验,那么可能要了解一些基本的入门课程就可以了,或者至少某种形式的教程,让你有了解基本概念. 但是,这里会比较少地介绍面向对象编程(OOP): OOP术语概述 类: 用户定义的原型对

repaint和reflow的相关知识

文章简介:页面重构应注意的repaint和reflow. 最近了解了下repaint和reflow的相关知识,觉得在页面重构过程中就应该考虑前端开发(js)人员对dom进行操作,能够减轻客户浏览器的鸭梨.在这里整理了一下相关资料,推荐看帖子底部的文章,如果觉得排版不够好请移步我的博客围观.这是一个讨论帖,抛砖引玉,大家说说自己工作中的经验~ 1. 什么是 repaint 和 reflow? 一个页面由两部分组成:DOM:描述该页面的结构render:描述 DOM 节点 (nodes) 在页面上如

介绍Ruby中的模块与混合类型的相关知识

  这篇文章主要介绍了Ruby中的模块与混合类型的相关知识,包括平常人们常说的多态与继承等相关知识点,需要的朋友可以参考下 模块是组合在一起的方法,类和常量.模块两个主要好处: 模块提供了一个命名空间,并避免名称冲突. 模块实现混合工厂. 模块定义了一个命名空间,一个沙箱中方法和常量可以自由使用,而不必担心踩到其他的方法和常数. 语法: ? 1 2 3 4 5 module Identifier statement1 statement2 ........... end 就像被命名为类常量模块中