在线

2654Perl 特殊变量

Perl 读取 .ini 风格配置文件之 Config::IniFiles

如果一个 Perl 脚本中有太多参数需要配置,使用命令行参数的方式就不太合适了。我们可以使用配置文件的方式来配置这些参数,刚好 Config::IniFiles 模块给我们提供了解析 .ini 风格配置文件的方法。重要的是其他语言,如 Python,也有 .ini 风格配置文件解析的包,所以用该方法,便于程序的通用性。

Config::IniFiles

先看一看 .ini 风格配置文件格式:

[section]          #参数模块
Parameter=Value    #该模块某参数的值。配置文件使用'#'或者';'注释

使用方法:

use Config::IniFiles; #加载模块
my $cfg = new Config::IniFiles( -file => "/path/configfile.ini" ); #读取配置文件
my $value = $cfg->val('Section', 'Parameter'); #读取参数

一个更加方便的读取方式:

my %ini
tie %ini, 'Config::IniFiles', ( -file => "/path/configfile.ini" );
#该方法把参数读进了二维哈希(引用的引用),即$ini{Section}{Parameter}

详细用法请参考: http://search.cpan.org/~wadg/Config-IniFiles-2.38/IniFiles.pm

2653Perl 数组

另外还有特殊标识 $_,表示遍历数组。

实例:

#!/usr/bin/perl
 
# 定义数组
@sites = qw(google taobao runoob facebook);
foreach(@sites){
    print $_."\n";
}

执行以上程序,输出结果为:

google
taobao
runoob
facebook

2033Perl 目录操作

Perl 递归目录其实可以用更简单的 File::Find 函式达成。

I. 實例

use warnings;
use utf8;
require File::Find;
# 宣告 STDOUT, STDIN, STDERR 都使用
# UTF-8 編碼方式。
binmode(STDOUT, ":encoding(utf8)");
binmode(STDIN, ":encoding(utf8)");
binmode(STDERR, ":encoding(utf8)");
# 用來顯示資料夾資訊的回呼函式。
sub callback {
  # Perl 假定 $_ 為預設的字串,所以 unless (-d) 等價於 unless (-d $_)
  # 參閱:http://www.runoob.com/perl/perl-special-variables.html (中文)
  #  或:https://perldoc.perl.org/perlvar.html (英文,`General Variables' 部份)
  #
  # -d 代表 directory 目錄,而 unless 代表「與條件相反才執行」。
  unless (-d) {
    print "檔案所在目錄的絕對路徑:$File::Find::dir\n";
    print "檔案所在位置的絕對路徑:$File::Find::name\n";
    print "檔案名稱:$_\n";
  };
};
# 這是要遞迴目錄的陣列。
# 此處假設要遞迴 /usr 和 ~/ (家目錄) 資料夾。
my @recursiveFolder = qw(/usr ~/);
# Let's recursive it!
# 要注意傳入的 sub 子程序必須要是個參照 (reference)
# 而非只是個普通的 sub 子程序。
File::Find::find(\&callback, @recursiveFolder);

II. 說明

File::Find 是一個應該能相容最近 Perl 版本的函式(我自己並沒找到 File::Find 最早於哪版引進,如果資料有誤也請幫忙修正 orz)。這個函式功能十分專一,也就只有遞迴功能。

以上的範例肯定看不出些什麼有用之處,但假如我們改一下例子 -- 只遞迴 MO 檔(一種已編譯翻譯檔的格式,先別在意):

sub callback {
  unless (-d || $_ !~ /.mo$/) {
    print "檔案所在目錄的絕對路徑:$File::Find::dir\n";
    print "檔案所在位置的絕對路徑:$File::Find::name\n";
    print "檔案名稱:$_\n";
  };
};

這麼寫就代表著「除了目錄和不以 .mo 作為結尾的檔案」。

III. 結尾

使用 File::Find 能讓遞迴檔案和資料夾的方式更加簡單。若你的 Perl 有遞迴需求,建議不要自己花時間重造輪子,直接用這個函式能事半功倍。

2032Perl 子程序(函数)

my 和 local 的区别

内部 -> 外部:

  • (1)my 和 local 都只在一个 block 里有效,出去就失效;
  • (2)但是 local 的变量可以继续在这个 block 中调用的子程序中存在;
  • (3)如果有与外界同名的变量,两者在 block 退出后都不影响外界同名变量;

外部 -> 内部:

(1)外部设置 my、local、缺省均队内有效,但是同名变量外部 my,在 block 内部 local 是不允许的。因为二者在 block 中调用的子程序中均有效,会冲突。

(2)如果在一个 block 中有一个 my 修饰的变量和外界的一个变量同名,而且又需要在这个 block 中使用外界变量时,两个办法:

  • 第一个办法,用 main 的 package 修饰这个变量名 $main::global
  • 第二个办法,用 our 修饰 our $global,那么该 block 中接下来出现的所有 $global 都是外界的 global。

(3)编写脚本时,注意作用域,防止外部影响内部。

2031Perl 数组

split 扩展说明

split [ PATTERN [ , EXPR [ , LIMIT ] ] ]

参数说明:

  • PATTERN:分隔符,默认为空格。
  • EXPR:指定字符串数。
  • LIMIT:如果指定该参数,则返回该数组的元素个数。

当采用LIMIT参数时,是指将数组分割成LIMIT个元素。而并非返回依分割符分割成的个数。举例:

$str = "a b c d e f";
print ("\$str:$str\n");
@arry = split (' ',$str);
$ary_len = @arry;
print("\@arry:@arry\n\$ary_len:$ary_len\n");
print("\@arry[4]:@arry[4] \@arry[5]:@arry[5]\n");
@arry2 = split (' ',$str,3);
$ary_len2 = @arry2;
print("\@arry2:@arry2\n\$ary_len2:$ary_len2\n");
print("\@arry2[0]:@arry2[0]\n\@arry2[1]:@arry2[1]\n\@arry2[2]:@arry2[2]\n");

输出结果:

$str:a b c d e f
@arry:a b c d e f
$ary_len:6
@arry[4]:e @arry[5]:f
@arry2:a b c d e f
$ary_len2:3
@arry2[0]:a
@arry2[1]:b
@arry2[2]:c d e f