China Open source community
站内导航:

 
 
 
当前位置: 首页 >> 程序设计 >> Perl 特殊变量
 

Perl 特殊变量

作者:      来源:zz     发表时间:2006-07-24     浏览次数:      字号:    

本文由 [color=red]chaoslawful[/color] 和鄙人共同翻译完成。
我原来翻译过一部分,不过没有翻完,后来幸亏 chaoslawful 的努力,所以才终于完成此文。
最新版本可以从这里获取(POD 格式):
http://svn.perlchina.org/trunk/POD2-CN/lib/POD2/CN/perlvar.pod

NAME

    perlvar - Perl 预定义变量

DESCRIPTION
  预定义名称
    后面列出的名称对 Perl 来说具有特殊含义。
    大多数标点名称都有合理的助记方法或类似于在 shell 中的用法。
    然而,如果你就是想用长变量名,那只要在程序开头加上

        use English;

    即可。这样会为所有短名称在当前包中创建长名称别名。
    其中一些甚至还有中间名,一般是从 awk 借用过来的。 一般来说,如果不需要
    $PREMATCH,$MATCH 和 $POSTMATCH,那最好使用

        use English '-no_match_vars';

    调用方式,因为它能避免在用正则表达式时出现效率降低的情况。见 English。

    依赖当前被选中文件句柄的变量可以通过在 IO::Handle
    对象上调用合适的对象方法来设置,
    但是这要比使用普通的内建变量效率低一些。(下面的概括行里包含的单词 HANDLE
    即指 IO::Handle 对象。) 首先你要声明

        use IO::Handle;

    然后就可以用

        method HANDLE EXPR

    或者更安全的形式,

        HANDLE->method(EXPR)

    每个方法都返回 IO::Handle 属性的旧值,同时接受一个可选的 EXPR。
    如果提供了该参数,则其指定了所涉及 IO::Handle
    属性的新值。如果不提供该参数, 大多数方法不改变当前值--除了
    autoflush(),它会假定给定了参数 1,稍有不同。

    载入 IO::Handle
    类是一项代价高昂的操作,因此你该知道如何使用常规的内建变量。

    这些变量中的少数几个是“只读的”。这意味着如果直接或者通过引用间接向该变
    量赋值, 就会引起一个运行时异常。

    在修改本文档中描述的大部分特殊变量的缺省值时都需要特别小心。多数情况下应
    该
    在修改之前局部化这些变量,如果不这么做,就可能影响依赖于你所修改特殊变量
    缺 省值的其他模块。下面是一次性读入整个文件的一种正确方法:

        open my $fh, "foo" or die $!;
        local $/; # enable localized slurp mode
        my $content = <$fh>;
        close $fh;

    但下面的代码就很糟糕:

        open my $fh, "foo" or die $!;
        undef $/; # enable slurp mode
        my $content = <$fh>;
        close $fh;

    因为一些模块可能想以默认的“行模式”从文件中读取数据,而一旦我们刚才
    列出的代码得到执行,在同一个 Perl 解释器内运行的所有其他代码读到的 $/
    全局值都会被改变。

    通常,在局部化一个变量时总是想让影响限制在尽可能小的范围内,因此
    应该自己建立一个 "{}" 块,除非你已经处于某些小的 "{}" 块内。例如:

        my $content = '';
        open my $fh, "foo" or die $!;
        {
            local $/;
            $content = <$fh>;
        }
        close $fh;

    下面是代码失控的一个例子:

        for (1..5){
            nasty_break();
            print "$_ ";
        }
        sub nasty_break {
            $_ = 5;
            # do something with $_
        }

    你可能希望上述代码打印出:

        1 2 3 4 5

    但实际上得到的却是:

        5 5 5 5 5

    为什么?因为 nasty_break() 修改了 $_ 而没有事先将其局部化。
    改正方法是增加 local():

            local $_ = 5;

    虽然在这样一个短小的例子里很容易发现问题,但在更复杂的代码中,如果不
    对特殊变量进行局部化更改就是在自找麻烦。

    下列内容按照先标量变量、后数组、最后散列的顺序排列。

    $ARG
    $_      默认的输入和模式搜索空间。下面的几对代码都是等同的:

                while (<>) {...}    # equivalent only in while!
                while (defined($_ = <>)) {...}

                /^Subject:/
                $_ =~ /^Subject:/

                tr/a-z/A-Z/
                $_ =~ tr/a-z/A-Z/

                chomp
                chomp($_)

            以下是几处即使没有写明 Perl 也会假定使用 $_ 的地方:

            *  各种单目函数,包括像 ord() 和 int() 这样的函数以及除 "-t"
               以外所有的文件 测试操作 ("-f","-d"),"-t" 默认操作 STDIN。

            *  各种列表函数,例如 print() 和 unlink()。

            *  没有使用 "=~" 运算符时的模式匹配操作 "m//"、"s///" 和
               "tr///"。

            *  在没有给出其他变量时是 "foreach" 循环的默认迭代变量。

            *  grep() 和 map() 函数的隐含迭代变量。

            *  当 "while" 仅有唯一条件,且该条件是对 "<FH>"
               操作的结果进行测试时,$_ 就是存放输入记录的默认位置。除了
               "while" 测试条件之外不会发生这种情况。

            (助记:下划线在特定操作中是可以省略的。)

    $a
    $b      是使用 sort() 时的特殊包变量,参见 "sort" in perlfunc。
            由于这一特殊性,$a 和 $b 即使在用了 "strict 'vars'"
            指示符以后也不需要声明(用 use vars 或者 our())。 如果想要在
            sort() 的比较块或者函数中使用它们,就不要用 "my $a" 或 "my $b"
            将其词法化。

    $<*digits*>
            含有上次模式匹配中捕获括号集合所对应的子模式,不包括已经退出的嵌
            套 块中匹配的模式。(助记:类似 \digits。)
            这些变量全都是只读的,对于 当前块来说具有动态作用域。

    $MATCH
    $&      含有上次成功的模式匹配所匹配到的字符串(不包括任何隐藏在块中的匹?
            浠虻鼻?块所包围的 eval())。(助记:同一些编辑器中的 & 类似。)
            该变量是只读的, 对于当前块来说具有动态作用域。

            在程序中任何地方使用该变量都会使所有正则表达式匹配产生可观的效率
            降低。 参见 "BUGS"。

    $PREMATCH
    $`      含有上次成功的模式匹配内容之前的字符串(不包括任何隐藏在块中的匹?
            浠虻鼻?块所包围的 eval)。(助记:"`"
            常常出现在引起的字符串之前。) 该变量是只读的。

            在程序中任何地方使用该变量都会使所有正则表达式匹配产生可观的效率
            降低。 参见 "BUGS"。

    $POSTMATCH
    $'      含有上次成功的模式匹配内容之后的字符串(不包括任何隐藏在块中的匹?
            浠虻鼻?块所包围的 eval())。(助记:"'"
            常常跟在引起的字符串之后。) 例如:

                local $_ = 'abcdefghi';
                /def/;
                print "$`:$&:$'\n";         # prints abc:def:ghi

            该变量只读且对于当前块具有动态作用域。

            在程序中任何地方使用该变量都会使所有正则表达式匹配产生可观的效率
            降低。 参见 "BUGS"。

    $LAST_PAREN_MATCH
    $+      含有上次成功的搜索模式中最后一个括号匹配的文本。在无法知道可选模
            式集中 到底哪一个匹配成功时,该变量是非常有用的。例如:

                /Version: (.*)|Revision: (.*)/ && ($rev = $+);

            (助记:积极一点儿向前看。)(译注:“积极”与“正号”是同一个单词?
            ? 该变量只读且相对于当前块具有动态作用域。

    $^N     含有上一次成功搜索模式中最近闭合的组(即最右边的右括号构成的组)所
            匹配 的文本。(助记:最近闭合的(可能)嵌套的括号。)
            (译注:嵌套的单词为 Nest。)

            该变量主要用在 "(?{...})"
            块的内部,以便检查最近匹配到的文本。例如,
            为了有效地用一个变量($1、$2 等等之外的变量)捕获文本,可以将
            "(...)" 替换为

                 (?:(...)(?{ $var = $^N }))

            像这样设置并使用 $var 就能把你从计算括号个数的烦恼中解放出来了。

            该变量对于当前块具有动态作用域。

    @LAST_MATCH_END
    @+      该数组保存了当前活动的动态作用域中最近成功的子匹配结束处的偏移量
            。 $+[0]
            为整个匹配在字符串中结束处的偏移量,这同用被匹配的变量调用 "pos"
            函数得到的值一样。该数组的第 *n* 个元素保存了第 *n* 个子匹配
            的偏移量,因此 $+[1] 就是紧接着 $1 结束处的偏移量,$+[2] 是
            紧接着 $2 结束处的偏移量,以此类推。可以用 $#+
            得知最近成功的匹配 中有多少个组。参见为 "@-" 变量给出的例子。

    $*      将其设为非零整数值就可以进行字符串内的多行匹配,设为
            0(或未定义值) 相当于告诉 Perl
            可以假定字符串都是单行的,从而能进行模式匹配的优化。当 $* 为 0
            或未定义值时,对含有多个换行符的字符串进行模式匹配会产生很难
            理解的结果。它默认为未定义值。(助记:* 匹配很多东西。)
            该变量只影响对 "^" 和 "$" 的解释。即使在 "$* == 0"
            时也可以搜索一个字面的换行符。

            在现在的 Perl 里不应使用 $*,在模式匹配中可以用 "/s" 和 "/m"
            修饰符取代 它的功能。

            对 $* 赋非数值量会触发一个警告(并使 $* 表现为 "$* == 0"),对 $*
            赋数值量则会隐含对其应用 "int"。

    HANDLE->input_line_number(EXPR)
    $INPUT_LINE_NUMBER
    $NR
    $.      为最后访问的文件句柄对应的当前行号。

            Perl 中每个文件句柄都记录从其中读出的行数。(Perl
            中行的概念也许和你不一 样,要看 $/ 的值是什么。)
            当从某个文件句柄中读出一行(通过 readline() 或 "<>")或对其调用
            tell() 或 seek() 时,$. 即成为那个句柄的行 计数器的别名。

            你可以通过向 $. 赋值来调整计数器,但这并不会实际移动文件指针。
            *局部化 $. 不会使对应文件句柄的行计数器局部化*,而只会局部化 $.
            和文件句柄的别名关系。

            关闭文件句柄时会复位 $.,但在没有 close()
            就重新打开一个已打开的文件句柄 时不会这样。更多细节参见 "I/O
            Operators" in perlop。"<>" 从不显式关闭文件,因此行号会在 ARGV
            文件之间持续增长(不过请看看 "eof" in perlfunc 中的例子)。

            你还可以用 "HANDLE->input_line_number(EXPR)"
            访问一个给定文件句柄的
            行计数器,这样就无需担心最后访问的是哪个句柄了。

            (助记:很多程序用“.”表示当前行号。)

    IO::Handle->input_record_separator(EXPR)
    $INPUT_RECORD_SEPARATOR
    $RS
    $/      为输入记录分隔符,默认为换行符。该变量会影响 Perl
            对“行”这一概念 的理解。其功能类似于 awk 中的 RS
            变量,在被设置为空字符串时同样
            会将空白行作为终止标志。(空白行不能含有任何空格或制表符。)
            你可以将其
            设置为含有多个字符的字符串,以匹配多字符的终止标志;也可以设为
            "undef" 以便一直读到文件结束。当文件含有连续的空白行时,把它设为
            "\n\n" 和设为 "" 有少许不同:设为 ""
            会把两个或更多连续的空白行视为单个 空白行;而设为 "\n\n"
            则只是盲目地假定其后输入的字符属于下一段,即使
            这些字符是换行符也一样。(助记:在引用诗句时会用 /
            作为行间的分隔。)

                local $/;           # enable "slurp" mode
                local $_ = <FH>;    # whole file now here
                s/\n[ \t]+/ /g;

            切记:$/ 的内容是一个字符串,而不是正则表达式。awk
            得在某些方面改进 一下了。:-)

            将 $/
            设为整数、存有整数的标量或可转换成整数的标量这些值的引用时,Perl
            会尝试读入记录而不是行,最大记录长度就是引用的那个整数。因此这段
            代码:

                local $/ = \32768; # or \"32768", or \$var_containing_32768
                open my $fh, $myfile or die $!;
                local $_ = <$fh>;

            会从 FILE 读取一条不长于 32768
            字节的记录。如果你不是在读取一个面向记录 的文件(或者所用的 OS
            没有面向记录的文件类型),那很可能每次读取都得到一
            整块的数据。若某条记录比你所设置的记录长度还大,就会把该记录拆成
            若干片 返回。

            在 VMS 上,记录读取是用 "sysread"
            的等价物完成的,因此最好不要在同一个
            文件上混合使用记录和非记录读。(这不太可能成为问题,因为任何你想?
            约锹寄J?读取的文件也许都不能在行模式下用。) 非 VMS 系统用普通
            I/O 进行读取,因此 在一个文件中混合记录和非记录读是安全的。

            参见 "Newlines" in perlport 以及 $.。

    HANDLE->autoflush(EXPR)
    $OUTPUT_AUTOFLUSH
    $|      若将该变量设为非零值,就会立刻强制进行刷新,并且当前选中的输出通
            道在每次 打印或写之后都会进行刷新。默认值为 0
            (不管选中的通道实际上是否被系统所缓冲, $| 只是告诉你 Perl
            是否在每次写完之后显式刷新)。典型情况下,若 STDOUT
            的输出是终端则是行缓冲的,否则就是块缓冲。设置该变量在向管道或套
            接字输出 时很有用,比如你正在 rsh 下运行一个 Perl
            程序并且想在输出时马上就能看到
            输出内容。该变量不影响输入缓冲。关于输入缓冲请参见 "getc" in
            perlfunc。 (助记:when you want your pipes to be piping hot.)

    IO::Handle->output_field_separator EXPR
    $OUTPUT_FIELD_SEPARATOR
    $OFS
    $,      为 print 的输出域分隔符。通常 print
            不经任何修饰就输出它的参数,要 得到更像 awk
            的行为,可以将该变量设置成和 awk 的 OFS 变量一样
            ,以指定域之间打印什么。(助记:当 print
            语句里有“,”时会打印的东西。)

    IO::Handle->output_record_separator EXPR
    $OUTPUT_RECORD_SEPARATOR
    $ORS
    $\      为 print 的输出记录分隔符。通常 print
            简单地原样输出它的参数,不增加
            任何结尾的换行符或其他表征记录结束的字符串。要得到更像 awk
            的行为, 可以将该变量设为同 awk 的 ORS 变量一样,以指定在 print
            的结尾输出 什么。(助记:设置 $\ 而不是在 print
            结尾加“\n”。另外,它长得和 $/ 很像,但却是你从 Perl
            那里拿“回”的东西。) (译注:“回”原文为
            单词“back”,还指代反斜杠“backslash”,起一语双关作用。)

    $LIST_SEPARATOR
    $"      该变量同 $,
            类似,但应用于向双引号引起的字符串(或类似的内插字符串)
            中内插数组和切片值的场合。默认为一个空格。(助记:我觉得显而易见?
            ?

    $SUBSCRIPT_SEPARATOR
    $SUBSEP
    $;      为模拟多维数组时的下标分隔符。如果你这样引用一个散列元素

                $foo{$a,$b,$c}

            实际上意思就是

                $foo{join($;, $a, $b, $c)}

            但是别这么写

                @foo{$a,$b,$c}      # a slice--note the @

            它的意思是

                ($foo{$a},$foo{$b},$foo{$c})

            默认为“\034”,同 awk 的 SUBSEP
            一样。如果你的散列键包含二进制数据, 可能 $;
            就没法包含任何可靠的值了。
            (助记:逗号(语法上的下标分隔符)是半个分号。是啊,我知道这完全没?
            兴捣

编辑 webmaster

 
 
 
评论
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •  
    中国源码网 - WWW.YUANMA.ORG - 中国开放源代码社区