perl 关于 do { local $/; <FILEHANDLE> } 语法糖

2018-09-07 03:17

1
2
3
open FILEHANDLE, '/etc/hosts' or die $!;
my $string = do { local $/; <FILEHANDLE> };
print($string);

该 perl 代码运行的输出结果大概是:

1
2
3
4
5
6
127.0.0.1       localhost

# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

即,/etc/hosts 的全部文件内容。

Q&A#

其中,难理解的是第二行,在 perl 的常规写法中,读取文件的完整内容应该是用一个 while 循环逐行读取:

1
2
3
4
5
open FILEHANDLE, '/etc/hosts' or die $!;
my $string;
while (<FILEHANDLE>) {
$string .= $_;
}

这里详细的来解释一下第二行:

  • do { <block> } 是 perl 中的代码块,函数的返回结果即 <block> 最后一个语句。
  • <FILEHANDLE> 是上述 do { <block> } 中的最后一个语句,即返回结果。而在 perl 中,<FILEHANDLE> 的返回结果根据不同的上下文,有两种不同的返回结果,即:
1
2
my $scalar = <FILEHANDLE>;    # 等号左边为标量时,返回文件的单行内容
my @array = <FILEHANDLE>; # 等号左边为数组时,返回文件的全部内容(文件的每行对应数组的每个元素)
  • $/ 变量的设置为该语法糖的关键。 $/ 变量是 输入的分隔符 (input record seperator),默认情况下是换行符。即 <FILEHANDLE> 在标量上下文时,返回单行文件内容的默认表现是由 $/ 变量决定的。而 local $/ 相当于 local $/ = undef
  • localmy 的区别:my 是创建一个新变量,而 local 则是临时改变一个变量的值(在作用域内)

整体解析下来就是,通过 do {} 创建一个临时的作用域,在作用域中改变 $\ 的值,改变了 <FILEHANDLE> 在标量上下文中的分隔符(由 \n 变为 undef),达到了读取整个文件内容的目的。

参考文章#


标签:perl

点击加载Disqus评论
Creative Commons © 2013 — 2018 xiao_cang | Theme based on fzheng.me & NexT | Hosted by Netlify