从函数复用开始:eval和do执行perl文件

当我们定义了一个功能比较通用的子程序,比如获取数值的绝对值。想要到处使用这个子程序,就得不断复制、粘贴这段绝对值函数的定义文本。显然,这是不太理想的方式。

于是,就将包含这个子程序的代码放进一个perl文件,然后通过特殊的语法去导入这个文件。

例如,文件sum.pm包含一个sum子程序,该子程序返回参数相加之和。

#!/usr/bin/env perl
# 注意,这里为了测试,没加use strict
sub sum {
my $sum;
$sum = map { $_ + $sum } $@
$name;
}
$name="longshuai"; # 全局变量属性

其中.pm后缀表示perl module。在perl 4的时候,使用的是.pl后缀,代表的是perl library。但现在,模块、包都使用.pm替代,而.pl主要代表perl程序。

eval语句导入文件

可以在其它perl文件中(如eval.pm)通过eval语句临时编译这个文件(sum.pm)中的语句。只不过在eval之前,需要先将sum.pm文件中的内容读取:

#!/usr/bin/env perl
#
use strict;
use warnings;
use 5.010; open my $fh,"<","sum.pm" or die "Can't open file: $!";
undef $/;
my $sum_code=<$fh>; # 读取代码保存到变量中
close $fh;
eval $sum_code; # eval评估编译这段代码,并执行
die $@ if $@; my $sum=sum(1,2,3); # 引用来自sum.pm的函数
say $sum;

上面的代码会报错。因为eval $sum_code是将来自sum.pm中的代码放在当前文件中临时进行编译,这段来自sum.pm的代码已经属于本文件。就等价于:

eval CODE;

所以,来自sum.pm中的全局属性$name在当前文件的use strict编译指示下将引发错误。所以,得将sum.pm内容中的$name去掉,或者加上my修饰。

eval中来自sum.pm的代码将能访问它所在代码块的词法变量。

do语句导入文件

也可以通过do语句临时编译这个文件,它将在当前程序(无论do语句是否是在代码块中)引入编译的结果(但除了子程序外的其它属性,由于一般会加上use strict,而导致为未声明的变量不可使用,间接地,所导入的文件中的变量$name将失效)。

#!/usr/bin/env perl
#
use strict;
use warnings;
use 5.010; {
do 'sum.pm';
die $@ if $@;
my $sum=sum(1,2,3);
say $sum;
# say $name; # 因为use strict的存在,而报错
}
say sum(2,3,4); # 出了语句块,函数仍有效

注意,do语句是在当前文件中引入变异结果,而不是当前代码块。

do导入文件时如果使用的是相对路径(如do 'sum1.pm'),将搜索@INC,搜索到后将更新%INC保持跟踪。

require导入文件

想象一下,如果在myperl.pm中使用do一次性导入两个文件sum1.pm、sum2.pm:

do 'sum1.pm';
die $@ if $@;
do 'sum2.pm';
die $@ if $@;

假设sum2.pm中也用了do语句导入sum1.pm,这样将会在myperl.pm中多次导入sum1.pm。其实第二次导入是多余的,尽管两次导入的内容是完全一致的,而且如果开启了use warnings,将会发出警告。

使用require语句可以解决这样重定义问题。

require '/perlapp/sum1.pm';   # 要给定正确的路径
require '/perlapp/sum2.pm';

require会在hash结构%INC中跟踪已经成功导入的文件,即使sum2.pm中也有require 'sum1.pm'语句。

为了跟踪是否曾经导入成功,要求所导入的文件最后要返回一个true,一般都会使用数值1作为所导入文件代码的结尾。并非一定是1,也可以是其它值,只要能表示最后这个文件是成功的就行。

例如,sum1.pm中:

#!/usr/bin/env perl
use strict;
use warnings;
use 5.010; sub sum {
my $sum;
$sum = map { $_ + $sum } $@
$name;
}
1; # 最后一行用1表示成功

以下是require相关的几点特性:

  • require的本质上do语句,do语句的本质是eval
  • require是在程序运行时执行的
  • 所导入文件中的任何语法错误都回直接die,因此可以省略die $@ if $@
  • require还能用于要求版本号,例如:require 5.010;
  • 在使用require时,如果使用的是裸词,例如require Foo::Bar;,将搜索@INC中的Foo/Bar.pm文件
  • 如果使用的不是裸词,如下。如果是绝对路径,则按照绝对路径查找,如果是相对路径,将从@INC路径下直接搜索Foo::Bar文件,显然文件一般不会这样命名,将会发出警告
    • require "Foo::Bar";:(双引号的存在)
    • require $class;其中$class="Foo::Bar"
    • require 'myperl.pm';

Perl导入代码文件的更多相关文章

  1. Java解析导入Excel文件后台代码实现

    使用MultipartFile上传Excel文件后端代码实现:(springmvc下的spring-webmvc (MultipartFile )上传) 由于POST一个包含文件上传的Form会以mu ...

  2. Spring Boot下的一种导入Excel文件的代码框架

    1.前言 ​ Spring Boot下如果只是导入一个简单的Excel文件,是容易的.网上类似的文章不少,有的针对具体的实体类,代码可重用性不高:有的利用反射机制或自定义注解,开发了Excel导入工具 ...

  3. mysql使用load导入txt文件所遇到的问题及解决方法

    导入txt文件,有导入向导这种方式: 另外可以使用load的方式导入.最开始使用以下代码插入: load data local infile 'F:\\Data\\predict_data.txt' ...

  4. Linux环境导入*.sql文件出现数据库为空

    登录mysql命令: 导入.sql文件: 或者: mysql -h127.0.0.1 -uroot -p userDb < /home/user.sql  按回车键后输数据库的密码 导入成功后, ...

  5. php通用安装程序,导入数据文件(.sql)的安装程序

    php通用安装程序,导入数据文件(.sql)的安装程序 该程序只需要1个php文件 和 1个数据文件,很方便调用.install/index.php         程序文件install/mycms ...

  6. Eclipse在已创建的project中导入其他文件

    Eclipse在已创建的project中导入其他文件 前两天被同事问到,如何通过不拷贝源文件的方式,在之前已经创建好的project中直接导入其他目录下的文件, 整理了一下,将目前所知道的eclips ...

  7. Java POI导入Excel文件

    今天在公司需要做个导入Excel文件的功能,所以研究了一下,参考网上的一些资料总算是做出来了,在此记录一下防止以后忘记怎么弄. 本人用的是poi3.8,所以需要的JAR包如下: poi-3.8.jar ...

  8. geotools导入shp文件到Oracle数据库时表名带下划线的问题解决

    问题: 最近在做利用geotools导入shp文件到Oracle表中,发现一个问题Oracle表名带下划线时导入失败,问题代码行: dsOracle.getFeatureWriterAppend(or ...

  9. 如何用CSC.exe来编译Visual C#的代码文件

    原文:如何用CSC.exe来编译Visual C#的代码文件 C#的编译过程      如何用CSC.exe来编译Visual C#的代码文件   Csc.exe 编译器的位置路径:C:\Window ...

随机推荐

  1. 网络操作系统 第七章 管理TCP/IP网络

    本章小结 本章介绍了TCP/IP的相关概念,并且在此处基础上,介绍了Windows Server 2008中使用TCP/IP网络配置工具实现网络连接和管理的方法,在Linux系统中,讲解了是如何使用图 ...

  2. redis在linux云服务器上完整的搭建步骤

    Redis的安装 搭建环境: 华为云linux服务器 Linux系统CneterOS-7.3 SSH客户端 Xshell6 安装c语言编译环境软件如下: 安装报错 然后找到了解决方法: 安装kerne ...

  3. FPGA开发随笔汇总

    点击标题即可进入相关随笔. DE-SOC开发板VrilogHDL开发相关部分: (本过程需要Verilog HDL 的基本语言基础) 1.FPGA的发展史及FPGA 的基础架构 2.首先看一下友晶DE ...

  4. vue computed计算属性和watch监听属性解疑答惑

    computed计算属性     计算属性类似于方法,用于输出data中定义的属性数据的结果,data数据变化时,计算属性的结果会同步变化,需要注意的是计算属性不可与data定义的属性同名. 相比于方 ...

  5. web专业课学习及往后方向发展

    日常10点起床!!!! web主要是网页设计,目前自我方向是学习web前端开发,熟悉掌握相关的编辑应用已达到能设计出满意的网页,日后继续学习后端等 ,成为全栈工程师.

  6. 恢复oracle数据从delete

    今天维护系统的时候没仔细看,误删了50行数据,然后想起来以前学过delete语句删除的数据是可以回复的,但是那个时候比较慌乱,也没有心情仔细看,反而是想到了一个歪招解决了问题,我有个良好的嗜好就是经常 ...

  7. Android中使用TabLayout实现Tab

    一.需求 activity + fragment实现tab,并可以滑动切换tab. 需要导入compile 'com.android.support:design:25.3.1' 二.layout实现 ...

  8. 凌华Express CVC D2550 Win7 64-bit无法正常关机的解决办法

    [问题现象]: 在Windows点击shutdown按钮后,显示器一直停在“正在关闭...”的界面上: 此时硬盘已经停止工作了: CPU没有发送S5信号,因此,主板上的电没有被切断: [解决办法]: ...

  9. 包建强的培训课程(15):Android App热修复技术

    @import url(/css/cuteeditor.css); Normal 0 10 pt 0 2 false false false EN-US ZH-CN X-NONE $([{£¥·‘“〈 ...

  10. MSMQ队列的简单使用

    微软消息队列-MicroSoft Message Queue(MSMQ) 使用感受:简单. 一.windows安装MSMQ服务 控制面板->控制面板->所有控制面板项->程序和功能- ...