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

2018-09-07 11: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),达到了读取整个文件内容的目的。

参考文章

除另有声明外 本博客文章均采用 知识共享(Creative Commons) 署名 4.0 国际许可协议 进行许可 转载请注明原作者与文章出处


标签: perl

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