zoukankan      html  css  js  c++  java
  • Perl导入代码文件

    从函数复用开始: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';
  • 相关阅读:
    非易失性存储器EEPROM
    NAND FLASH系统的权衡利弊
    Python爬虫爬取爱奇艺电影片库首页
    xpath解析爱奇艺电影网页数据
    BeautifulSoup 库 和 re 库 解析腾讯视频电影
    《人月神话》读书笔记(一)
    Python爬取腾讯视频电影名称和链接(一)
    配置腾讯云轻量级linux服务器用到的资源和步骤
    CSS样式中的各种居中方式
    CSS浮动---float
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/9770651.html
Copyright © 2011-2022 走看看