perl之glob — 类型团 (函数)

首页 | 新闻 | 交流 | 问吧 | 文档 | 手册 | 下载 | 博客

perl之glob — 类型团 (函数)

作者:  时间: 2010-11-16

glob在Perl里有两个意思,一个是数据类型“类型团”(Typeglob),一个是函数。

----------------------------
(一)
Perl 里面有种特殊的类型叫类型团(typeglob)用以保留整个符号表记录。(符号表记录 *foo 包括 $foo, @foo, %foo,&foo 和其他几个 foo 的简单解释值。)类型团(typeglob)的类型前缀上一个 *,因为它代表所有类型。

类型团(typeglob)(或由此的引用)的一个用途是是用于传递或者存储文件句柄。如果你想保存一个文件句柄,你可以这么干:

$fh = *STDOUT;

或者作为一个真的引用,象这样:

$fh = \*STDOUT;

这也是创建一个本地文件句柄的方法,比如:

   sub newopen {
      my  $path = shift;
      local *FH;      # 不是my() 或 our ()
      open(FH,$path ) or return undef;
      return *FH:      # 不是\*FH!
   }
   $fh = newopen('/etc/passwd');
参阅 open 函数获取另外一个生成新文件句柄的方法。
类型团如今的主要用途是把一个符号表取另一个符号表名字做别名。别名就是外号,如果你说:

*foo = *bar;

那所有叫“foo”的东西都是每个对应的叫“bar”的同意词。你也可以通过给类型团赋予引用实现只给某一个变量取别名:

*foo = \$bar;

这样 $foo 就是 $bar 的一个别名,而没有把 @foo 做成 @bar 的别名,或者把 %foo 做成 %bar 的别名。所有这些都只影响全局(包)变量;词法不能通过符号表记录访问。象这样给全局变量别名看起来可能有点愚蠢,不过事实是整个模块的输入/输出机制都是建筑在这个特性上的,因为没有人要求你正在当别名用的符号必须在你的名字空间里。因此:

local *Here::blue = \$There::green;

临时为 $There::green 做了一个叫 $Here::blue 的别名,但是不要给 @There:green 做一个叫 @Here::blue 的别名,或者给 %There::green 做一个 %Here::blue 的别名。幸运的是,所有这些复杂的类型团操作都隐藏在你不必关心的地方。参阅第八章的“句柄参考”和“符号表参考”,第十章的“符号表”,和第十一章,模块,看看更多的关于类型团的讨论和重点。

----------------------------
----------------------------
(二)

glob EXPR
glob
这个函数把 EXPR 的值带着 shell 那样的文件名扩展返回。它是实现 <*> 操作符的内部函数。

由于历史原因,这个算法和 csh(1) 的扩展风格相匹配,而不是 Bourne shell 的。早于 5.6 版本的 Perl 使用了一个外部的处理,但 5.6 及以后的版本在内部进行聚团的工作。那些第一个字符是点(“.”)的文件被忽略,除非这个字符是明确匹配的。一个星号(“*”)匹配任意字符的任意序列 (包括空)。一个问号(“?”)匹配任意一个字符。一个方括弧序列(“[ ... ]”)声明一个简单的字符表,比如“[chy0-9]”。字符表可以用音调符号取反,象“*.[^oa]”,它匹配任意非点文件,这些文件的文件名博爱喊 一个点,后面跟着一个字符在文件名尾部,但这个字符既不能是“a”也不能是“o”。一个波浪号(“~”)扩展成一个家目录,象“~/.*rc”是指当前用 户的所有 “rc”文件,或者“~jane/Mail/*”似乎所有 Jane 的邮件文件。花括弧可以用于候补,象在“!/.{mail,ex,csh,twm,}rc”里面的是获取那些特定的 rc 文件。

如果你想聚集那些可能包含空白的文件名,你可能需要直接使用 File::Glob 模块,因为老祖父 glob 把空白用于分隔多个模式,比如 <*.c *.h>。更多细节,请参阅第三十二章的 File::Glob。调用 glob (或者 <*> 操作符)自动 use 该模块,因此如果该模块莫名其妙地从你的库里消失了,那么就会抛出一个例外。

当你调用 open 的时候,Perl 并不扩展通配符,包括波浪号。你需要先把结果 glob 起来。


   open(MAILRC, "~/.mailrc")      # 错:波浪号是一个 shell 的东西
      or die "can't open ~/.mailrc: $!";

   open(MAILRC, (glob("~/.mailrc"))[0])   # 先扩展波浪号
      or die "can't open ~/.mailrc: $!";
glob 函数和 Perl 的类型团的概念没有任何关系,只不过它们都用 * 代表多个项。

 

 

---------------------------- 


参考资料:Perl语言编程(第三版)