Manpages

NAME

perldata − Perl 数 据 类 型

DESCRIPTION 描 述

Variable names 变 量 名

Perl 有 三 种 内 建 的 数 据 类 型 : 标 量 , 数 组 和 关 联 数 组 ( 即 "哈 希 表 , hash") 。 数 组 以 数 字 为 索 引 , 通 常 以 0开 始 , 升 序 排 列 。 哈 希 表 以 与 值 相 关 联 的 字 符 串 为 索 引 , 内 部 排 列 是 无 序 的 。

值 通 常 通 过 一 个 变 量 名 ( 或 变 量 名 的 引 用 ) 来 引 用 。 变 量 名 的 前 缀 字 符 显 示 了 值 的 数 据 类 型 。 其 余 部 分 指 明 了 引 用 的 是 哪 一 个 特 定 的 值 。 通 常 变 量 名 是 一 个 唯 一 的 标 识 符 , 以 字 母 或 下 划 线 开 始 , 包 括 字 母 、 下 划 线 和 数 字 。 某 些 情 况 下 , 也 可 以 是 以 "::" 分 隔 的 一 串 标 识 符 (或 者 是 过 时 的 "’"); 除 了 最 后 一 个 , 其 它 都 是 包 名 , 用 来 定 位 最 后 一 个 标 识 符 所 在 的 位 置 (详 情 参 见 perlmod 中 的 Packages)。 可 以 用 一 个 简 单 的 标 识 符 来 替 代 它 , 利 用 引 用 就 可 以 。 下 文 有 详 述 , 也 可 参 见 perlref .

Perl 也 有 内 建 的 变 量 , 其 名 称 不 遵 循 这 一 规 则 。 它 们 名 称 古 怪 , 这 样 可 以 避 免 与 你 的 变 量 名 冲 突 。 模 式 匹 配 中 被 匹 配 到 的 字 符 串 是 以 "$" 加 一 个 数 字 的 变 量 名 来 存 放 的 (参 见 the perlop manpage 和 the perlre manpage)。 另 外 , 还 有 几 个 使 你 可 以 介 入 perl 内 部 工 作 的 特 殊 变 量 , 其 名 称 中 包 含 标 点 和 控 制 字 符 ( 参 见 perlvar )

标 量 以 ’$’开 始 , 即 使 它 是 数 组 或 哈 希 的 元 素 也 是 如 此 。 可 以 把 ’$’ 理 解 为 ’s’ , 表 示 scalar( 标 量 ) 。 ( 译 者 注 : 此 处 根 据 有 关 文 档 , 做 了 改 动 , 下 面 的 @处 也 是 这 样 )

    $days               # 简 单 标 量  "days"
    $days[28]           # 数 组  @days的 第 29个 元 素
    $days{’Feb’}        # 哈 希  %days的  ’Feb’ 所 对 应 的 值
    $#days              # 数 组  @days的 最 后 一 个 元 素 的 索 引 值

整 个 数 组 ( 或 数 组 和 哈 希 的 局 部 ) 以 ’@’开 始 , 它 类 似 英 文 中 的 "these" 或 "those" (这 些 ……那 些 ……), 表 示 期 望 有 多 个 值 。

    @days               # ($days[0], $days[1],... $days[n])
    @days[3,4,5]        # 即  ($days[3],$days[4],$days[5])
    @days{’a’,’c’}      # 即  ($days{’a’},$days{’c’})

整 个 哈 希 以 ’%’ 开 始 :

    %days               # (key1, val1, key2, val2 ...)

另 外 , 子 程 序 以 ’&’来 表 示 , 但 有 时 在 不 引 起 误 解 的 情 况 下 也 可 以 不 用 , 就 象 "do" 在 英 语 中 常 常 省 略 一 样 。 符 号 表 项 以 ’*’ 作 为 开 始 字 符 , 不 过 你 现 在 还 不 用 关 心 这 个 (if ever ;-)

每 一 种 数 据 类 型 都 有 它 自 己 的 名 字 空 间 , 常 量 标 识 符 也 一 样 。 这 意 味 着 你 可 以 使 用 同 一 个 名 字 来 命 名 标 量 、 数 组 、 哈 希 、 文 件 句 柄 、 目 录 句 柄 、 子 程 序 、 格 式 或 标 签 。 即 $foo@foo 是 不 同 的 变 量 。 也 即 意 味 着 $foo[1]@foo 的 一 部 分 , 而 不 是 $foo的 一 部 分 . 这 看 来 有 些 怪 异 , 不 过 很 正 常 , 因 为 它 本 来 就 怪 异 。

因 为 变 量 名 以 ’$’, ’@’, 或 ’%’开 始 , 保 留 词 对 变 量 没 有 什 麽 影 响 。 保 留 词 影 响 的 是 标 签 和 文 件 句 柄 , 因 为 它 们 不 是 以 特 殊 字 符 前 缀 开 始 的 。 你 不 能 用 "log" 来 命 名 文 件 句 柄 , 因 为 它 是 保 留 词 ( 提 示 : 你 可 以 用 "open(LOG,’logfile’)" 而 不 是 "open(log,’logfile’)"). 使 用 大 写 的 文 件 句 柄 既 增 加 了 可 读 性 , 又 减 少 了 冲 突 的 发 生 。 大 小 写 是 有 意 义 的 −−" FOO ", "Foo", 和 "foo" 是 不 同 的 名 称 。 以 字 母 或 下 划 线 开 始 的 名 称 可 以 包 含 数 字 和 下 划 线 。

可 以 用 一 个 返 回 相 关 引 用 的 表 达 式 来 替 换 这 样 的 变 量 名 。 参 见 perlref

以 数 字 开 始 的 变 量 名 只 能 包 含 数 字 。 不 是 以 字 母 、 下 划 线 或 数 字 开 始 的 变 量 名 只 能 含 有 一 个 字 符 , 如 : $%$$. (大 部 分 这 样 的 变 量 都 有 特 殊 的 意 义 。 例 如 , $$ 是 当 前 进 程 的 id。 )

Context 上 下 文

在 Perl 中 有 时 操 作 或 值 的 意 义 取 决 于 该 操 作 或 值 所 处 的 上 下 文 。 有 两 个 主 要 的 上 下 文 : 列 表 和 标 量 上 下 文 。 相 当 一 部 分 操 作 在 需 要 列 表 的 上 下 文 中 返 回 列 表 , 在 需 要 标 量 的 上 下 文 中 返 回 标 量 。 这 在 有 关 该 操 作 的 文 档 中 会 提 到 。 换 句 话 讲 , Perl会 重 载 这 些 操 作 符 。 英 语 中 的 某 些 词 , 如 ’fish’和 ’sheep’与 此 类 似 。

操 作 可 以 根 据 不 同 的 上 下 文 返 回 不 同 的 值 。 例 如 , 如 果 这 样 写 :

    int( <STDIN> )

integer 操 作 提 供 标 量 上 下 文 给 <> 操 作 符 , <> 会 从 STDIN 读 入 一 行 返 回 给 integer 操 作 , 然 后 它 返 回 其 中 的 整 型 量 。 但 如 果 你 这 样 写 :

    sort( <STDIN> )

sort操 作 提 供 列 表 上 下 文 给 <>, <>会 读 入 STDIN中 的 每 一 行 直 到 结 束 , 然 后 将 其 传 递 给 sort, sort然 后 将 其 排 序 输 出 。

赋 值 比 较 特 殊 , 左 侧 的 参 数 决 定 了 右 侧 的 参 数 的 上 下 文 。 赋 值 给 标 量 , 则 右 侧 参 数 的 上 下 文 是 标 量 上 下 文 ; 赋 值 给 数 组 或 哈 希 , 则 右 侧 参 数 的 上 下 文 是 列 表 上 下 文 。 赋 值 给 列 表 ( 或 片 段 , 其 实 也 是 列 表 ) , 右 侧 的 上 下 文 也 是 列 表 上 下 文 。

当 你 使 用 "use warnings" 编 译 指 示 或 Perl 的 −w 参 数 时 , 你 可 能 会 看 到 这 样 的 警 告 : 在 "无 效 的 上 下 文 , void context" 中 使 用 了 常 量 或 函 数 。 无 效 上 下 文 的 意 思 是 值 被 丢 弃 不 用 , 比 如 只 包 含 有 ""fred";" 的 语 句 ; 或 是 "getpwuid(0);";. 在 要 求 列 表 上 下 文 的 函 数 被 标 量 上 下 文 环 境 调 用 时 ,也 会 出 现 这 个 警 告 .

用 户 定 义 的 子 程 序 可 能 会 需 要 查 看 上 下 文 是 无 效 , 标 量 , 还 是 列 表 。 不 过 , 大 多 数 并 不 需 要 这 么 做 。 因 为 标 量 和 列 表 会 自 动 插 入 到 一 个 列 表 中 。 参 见 perlfunc 中 的 "wantarray" 以 了 解 如 何 辨 明 你 的 函 数 调 用 时 的 上 下 文 。

Scalar values 标 量

Perl 中 的 所 有 数 据 都 是 标 量 , 标 量 的 数 组 ,标 量 的 哈 希 . 标 量 可 以 是 三 种 不 同 的 值 : 数 字 , 字 符 (串 ), 引 用 . 通 常 , 不 同 值 之 间 的 转 换 是 透 明 的 . 虽 然 一 个 标 量 不 可 能 有 多 个 值 , 但 是 它 可 以 是 一 个 包 含 多 个 值 的 数 组 或 哈 希 的 引 用 .

标 量 不 一 定 非 此 即 彼 . 不 需 要 声 明 变 量 的 类 型 是 "字 符 串 ","数 字 ","引 用 "或 其 它 什 麽 . 因 为 标 量 会 自 动 转 换 , 所 以 其 类 型 不 用 关 心 . Perl 是 上 下 文 多 形 语 言 ,它 的 标 量 可 以 是 字 符 串 ,数 字 或 引 用 (包 括 对 象 ). 其 中 字 符 串 和 数 字 在 大 多 数 情 况 下 并 没 有 什 麽 不 同 , 引 用 是 强 化 的 ,不 可 变 的 带 有 内 建 引 用 计 数 和 析 构 器 的 指 针 .

标 量 在 不 是 空 字 符 串 和 数 字 0的 时 候 被 解 释 为 真 TRUE. 布 尔 上 下 文 是 这 样 一 种 上 下 文 , 这 时 不 会 发 生 数 字 或 字 符 串 的 自 动 转 换 .

有 两 种 空 字 符 串 (有 时 以 "empty"表 示 ), 定 义 了 的 和 未 定 义 的 . 定 义 了 的 空 字 符 串 就 是 长 度 为 零 的 字 符 串 ,如 "". 未 定 义 的 空 字 符 串 是 一 个 值 ,这 个 值 表 示 某 事 物 并 没 有 真 实 值 与 它 对 应 , 比 如 出 错 , 或 到 达 文 件 尾 , 或 者 你 引 用 一 个 未 定 义 的 数 组 或 哈 希 的 元 素 时 ,都 会 返 回 一 个 未 定 义 的 空 字 符 串 . 虽 然 在 早 期 Perl 中 ,在 要 求 已 定 义 变 量 的 上 下 文 中 使 用 未 定 义 的 变 量 可 以 使 得 该 变 量 得 到 定 义 , 现 在 却 只 有 在 特 殊 的 情 况 下 才 会 出 现 这 种 结 果 ,参 见 the perlref manpage. 可 以 用 defined() 函 数 来 检 测 标 量 是 否 已 经 定 义 (对 数 组 和 哈 希 无 效 ),也 可 以 用 undef() 去 除 对 变 量 的 定 义 .

要 弄 清 楚 一 个 字 符 串 是 否 是 有 效 的 非 0数 字 ,只 要 看 它 是 不 是 数 字 0和 字 母 "0" 就 足 够 了 (不 过 这 在 使 用 -w参 数 时 ,会 显 示 警 告 ). 因 为 非 数 字 的 字 符 串 被 看 作 0, 与 awk中 相 似 :

    if ($str == 0 && $str ne "0")  {
        warn "That doesn’t look like a number";
    }

这 种 方 法 可 能 是 最 好 的 ,因 为 如 若 不 然 你 不 会 正 确 对 待 IEEE 的 注 释 ,比 如 "NaN" 和 无 穷 大 . 别 的 时 候 , 你 可 能 更 愿 意 用 POSIX::strtod() 函 数 或 是 正 则 表 达 式 来 检 测 字 符 串 是 否 能 用 做 数 字 (参 见 perlre).

    warn "has nondigits"        if     /\D/;
    warn "not a natural number" unless /^\d+$/;             # rejects -3
    warn "not an integer"       unless /^-?\d+$/;           # rejects +3
    warn "not an integer"       unless /^[+-]?\d+$/;
    warn "not a decimal number" unless /^-?\d+\.?\d*$/;     # rejects .2
    warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?⎪\.\d+)$/;
    warn "not a C float"
        unless /^([+-]?)(?=\d⎪\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;

数 组 的 长 度 是 标 量 . 通 过 $#days你 可 以 知 道 @days的 长 度 . 技 术 上 讲 ,这 不 是 数 组 的 长 度 ; 而 是 最 后 一 个 元 素 的 下 标 ,因 为 第 一 个 元 素 的 下 标 是 0. 对 $#days 赋 值 会 改 变 数 组 的 长 度 . 以 这 种 方 式 减 少 数 组 的 话 , 会 破 坏 其 中 的 值 , 再 增 加 其 长 度 也 不 能 恢 复 . (Perl 4中 是 可 以 的 , 我 们 改 变 了 它 以 确 保 析 构 器 被 及 时 调 用 .)

你 可 以 使 用 一 些 小 技 巧 来 预 扩 展 一 个 数 组 (如 果 你 知 道 它 将 会 变 得 很 大 的 话 ). 可 以 用 给 超 出 数 组 范 围 的 元 素 赋 值 的 方 法 扩 展 数 组 . 可 以 给 数 组 赋 值 一 个 空 列 表 以 清 空 数 组 . 下 面 语 句 等 价 :

    @whatever = ();
    $#whatever = -1;

数 组 处 于 标 量 上 下 文 中 时 , 返 回 值 是 数 组 的 长 度 . (列 表 在 标 量 上 下 文 中 ,返 回 值 是 列 表 的 最 后 一 个 元 素 ,像 是 C中 的 逗 号 操 作 符 , 而 内 建 函 数 的 返 回 值 由 它 们 自 己 决 定 .) 以 下 语 句 为 真 :

    scalar(@whatever) == $#whatever - $[ + 1;

Perl 5 改 变 了 $[ 的 意 义 : 不 必 担 心 别 的 程 序 改 变 了 $[ 的 值 . (换 言 之 ,不 推 荐 使 用 $[ ) 所 以 ,可 以 写 成 这 样 :

    scalar(@whatever) == $#whatever + 1;

有 些 程 序 员 为 了 明 确 起 见 , 会 使 用 显 式 的 转 换 :

    $element_count = scalar(@whatever);

当 哈 希 处 于 标 量 上 下 文 中 时 , 如 果 哈 希 为 空 , 返 回 值 为 假 , 如 果 非 空 , 返 回 值 为 真 ; 说 得 更 精 确 些 , 返 回 值 是 个 字 符 串 , 由 已 经 使 用 的 存 储 段 和 分 配 的 全 部 存 储 段 组 成 ,二 者 之 间 以 斜 杠 分 隔 . 这 可 以 用 来 反 映 Perl的 哈 希 算 法 的 好 坏 . 例 如 , 你 的 哈 希 中 有 10,000个 元 素 ,但 是 %HASH 的 标 量 值 为 "1/16", 则 说 明 仅 用 到 了 16个 存 储 段 中 的 一 个 , 也 许 10,000个 元 素 都 在 这 一 个 存 储 段 中 . 最 好 不 要 发 生 这 种 情 况 .

你 可 以 预 先 为 哈 希 分 配 空 间 , 这 要 使 用 给 keys() 函 数 赋 值 的 方 法 来 实 现 . 实 际 分 配 的 空 间 是 大 于 所 给 值 的 二 的 幂 :

    keys(%users) = 1000;                # 分 配  1024 空 间

Scalar value constructors 标 量 数 据 构 造

数 值 常 量 有 以 下 浮 点 和 整 数 格 式 :

    12345
    12345.67
    .23E-10             # a very small number
    3.14_15_92          # a very important number
    4_294_967_296       # underscore for legibility
    0xff                # hex
    0xdead_beef         # more hex
    0377                # octal
    0b011011            # binary

在 数 字 常 量 中 可 以 在 数 字 间 插 入 下 划 线 来 增 加 可 读 性 。 例 如 , 可 以 三 位 一 组 (Unix 样 式 的 分 组 , 例 如 0b110_110_100), 或 者 四 位 一 组 (来 表 示 nibbles, 例 如 0b1010_0110), 或 者 其 他 分 组 。

字 符 串 通 常 以 单 引 号 或 双 引 号 括 起 . 与 标 准 Unix shells中 的 引 号 相 似 : 双 引 号 可 以 接 收 转 义 和 变 量 ; 单 引 号 不 可 以 (除 了 "\’""\\")). C 样 式 的 转 义 字 符 可 以 用 来 输 入 新 行 , 跳 格 等 字 符 , 转 义 字 符 的 列 表 可 以 参 见 perlop 中 的 "Quote and Quote-like Operators"

十 六 进 制 ,八 进 制 ,或 二 进 制 以 字 符 串 形 式 表 示 (如 :’0xff’),不 能 自 动 转 换 为 十 进 制 形 式 . hex() 和 oct() 函 数 可 以 实 现 转 换 . 参 见 perlfunc 中 的 hex 和 oct 了 解 详 情 .

可 以 在 字 符 串 中 直 接 加 入 新 行 . 字 符 串 中 的 变 量 只 能 是 标 量 ,数 组 和 数 组 或 哈 希 的 片 段 (换 言 之 , 以 $或 @开 始 , 后 跟 下 标 .). 以 下 语 句 打 印 ’’The price is $100.’’

    $Price = ’$100’;    # not interpolated
    print "The price is $Price.\n";     # interpolated

perl 中 没 有 double interpolation, 因 此 $100 保 持 不 变 。

正 如 在 有 些 shell中 一 样 , 你 可 以 用 花 括 号 括 起 变 量 名 , 以 便 区 分 变 量 名 和 其 后 的 字 母 及 下 划 线 . 如 果 要 将 一 个 变 量 改 写 为 字 符 串 时 , 必 须 这 样 做 , 以 避 免 与 后 面 的 双 冒 号 或 单 引 号 连 接 起 来 , 否 则 会 被 当 作 包 名 :

    $who = "Larry";
    print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n";
    print "We use ${who}speak when ${who}’s here.\n";

如 果 没 有 花 括 号 , Perl会 寻 找 $whospeak, $who::0, 和 $who’s 变 量 . 后 两 个 是 不 存 在 的 who 包 中 的 $0 和 $s.

实 际 上 , 花 括 号 中 的 标 识 符 必 须 是 字 符 串 , 哈 希 的 下 标 也 必 须 是 字 符 串 . 都 不 需 要 引 号 , 前 面 的 例 子 $days{’Feb’} 可 以 写 作 $days{Feb} 引 号 会 自 动 加 上 . 但 是 下 标 中 的 其 它 复 杂 内 容 被 解 释 为 表 达 式 .

Version Strings

注 意 : Version Strings (v−strings) have been deprecated. They will not be available after Perl 5.8. The marginal benefits of v−strings were greatly outweighed by the potential for Surprise and Confusion.

类 似 "v1.20.300.4000" 这 样 的 形 式 被 解 释 为 一 个 字 符 串 . 这 种 形 式 称 为 v−strings, 提 供 了 更 易 读 的 方 法 来 构 造 字 符 串 , 比 起 "\x{1}\x{14}\x{12c}\x{fa0}" 更 加 易 读 . 这 在 表 示 Unicode 字 符 串 时 很 有 用 , 在 使 用 字 符 串 比 较 命 令 ("cmp", "gt", "lt" 等 )比 较 版 本 号 时 也 非 常 有 用 . 如 果 其 中 的 点 号 多 于 两 个 , 则 开 始 的 "v" 可 以 省 略 .

    print v9786;              # prints UTF-8 encoded SMILEY, "\x{263a}"
    print v102.111.111;       # prints "foo"
    print 102.111.111;        # same

这 种 形 式 可 以 用 于 require 和 use 中 作 版 本 检 查 ."$^V" 特 殊 变 量 中 的 Perl版 本 号 就 是 以 这 种 形 式 保 存 的 . 参 见 perlvar 中 的 "$^V" 注 意 使 用 v−strings 来 保 存 IPv4 地 址 是 不 可 移 植 的 , 除 非 同 时 使 用 Socket 包 的 inet_aton()/inet_ntoa() 函 数 。

注 意 从 Perl 5.8.1 开 始 单 个 数 字 的 v−strings (类 似 "v65") 如 果 在 "=>" 操 作 符 (通 常 用 来 从 hash 值 中 区 分 开 hash 键 ) 之 前 , 不 是 一 个 v−strings, 而 是 解 释 为 字 符 串 (’v65’)。 在 Perl 5.6.0 到 Perl 5.8.0 它 一 直 是 v−strings, 但 是 这 样 带 来 了 更 多 混 淆 和 错 误 而 不 是 优 点 。 多 个 数 字 的 v−strings, 类 似 "v65.66"65.66.67, 继 续 总 是 被 当 作 v−strings

特 殊 常 量

特 殊 变 量 __FILE__, __LINE__, 和 __PACKAGE__ 代 表 当 前 文 件 名 ,行 号 ,和 包 名 . 它 们 只 能 作 为 单 独 的 符 号 来 使 用 ; 不 能 用 于 字 符 串 中 内 插 . 如 果 没 有 当 前 包 (用 "package;" 指 令 来 实 现 ), 则 __PACKAGE__ 是 一 个 未 定 义 的 值 .

控 制 字 符 ^D 和 ^Z, 以 及 __END__ 和 __DATA__ 变 量 可 以 表 示 文 件 的 逻 辑 结 束 . 其 后 的 文 本 被 忽 略 .

__DATA__ 之 后 的 文 本 可 以 通 过 文 件 句 柄 "PACKNAME::DATA" 读 取 , "PACKNAME" 是 __DATA__ 所 在 的 包 的 名 称 . 句 柄 指 向 __DATA__ 后 面 的 文 本 . 读 取 结 束 程 序 会 自 动 关 闭 该 句 柄 "close DATA". 为 了 与 __DATA__ 还 没 有 出 现 以 前 已 经 存 在 的 程 序 兼 容 , __END__ 在 顶 级 脚 本 中 与 __DATA__ 性 质 相 同 (在 用 "require""do" 调 用 时 是 不 同 的 ) 不 过 可 以 通 过 "main::DATA" 来 调 用 其 中 的 内 容 .

参 见 SelfLoader 详 细 了 解 __DATA__, 其 中 还 有 例 子 . 要 注 意 在 BEGIN 块 中 无 法 读 取 DATA句 柄 : 因 为 BEGIN 块 在 编 译 时 即 被 执 行 , 而 此 时 __DATA__ (或 __END__) 还 未 被 程 序 看 到 .

裸 词

在 文 法 上 没 有 特 殊 意 义 的 词 语 都 被 看 作 字 符 串 . 称 之 为 "裸 词 ". 和 文 件 句 柄 以 及 标 签 一 样 , 仅 包 含 小 写 字 母 的 裸 词 有 可 能 在 将 来 与 程 序 中 的 保 留 词 发 生 冲 突 , 实 际 上 ,当 你 使 用 "use warnings" 语 句 ,或 是 −w 选 项 时 , Perl会 对 此 提 出 警 告 . 一 些 人 可 能 希 望 完 全 禁 止 这 样 的 词 . 如 果 有 如 下 语 句 :

    use strict ’subs’;

那 么 不 能 被 解 释 为 子 程 序 的 裸 词 会 引 起 编 译 时 错 误 . 这 种 限 制 到 块 结 束 时 终 止 . 而 内 部 的 块 可 以 撤 消 这 一 限 制 , 用 "no strict ’subs’"

数 组 合 并 分 隔 符

数 组 和 序 列 被 合 并 为 双 引 号 引 用 的 字 符 串 时 , 以 变 量 $" 指 定 的 值 (如 果 指 定 了 "use English;" 那 么 是 $LIST_SEPARATOR 的 值 ) 作 为 分 隔 符 , 默 认 是 空 格 。 下 列 语 句 等 价 :

    $temp = join($", @ARGV);
    system "echo $temp";
    system "echo @ARGV";

在 搜 索 模 式 中 (在 双 引 号 字 符 串 中 也 是 )有 一 个 易 混 淆 之 处 : "/$foo[bar]/" 应 该 是 "/${foo}[bar]/" ("[bar]" 是 正 则 表 达 式 的 字 符 类 ) 还 是 "/${foo[bar]}/"/ ("[bar]" 是 数 组 @foo 的 下 标 ) 呢 ? 如 果 @foo 不 存 在 , 那 很 明 显 它 应 该 是 字 符 类 . 如 果 @foo 存 在 , Perl 会 尽 力 猜 测 "[bar]" 的 含 义 , 且 它 几 乎 总 是 对 的 . 如 果 它 猜 错 了 , 或 者 你 比 较 偏 执 , 你 可 以 使 用 花 括 号 .

here−document 的 语 法 已 经 被 移 动 到 perlop 中 的 "Quote and Quote-like Operators"

List value constructors 列 表 值 构 造

列 表 是 用 逗 号 分 开 的 各 个 值 组 成 的 (如 果 优 先 级 需 要 的 话 ,外 面 还 要 用 圆 括 号 包 围 ):

    (LIST)

在 不 需 要 列 表 的 上 下 文 中 , 列 表 的 值 是 最 后 一 个 元 素 的 值 , 这 与 C中 的 逗 号 操 作 符 类 似 . 例 如 :

    @foo = (’cc’, ’-E’, $bar);

将 列 表 赋 给 数 组 @foo, 但 是

    $foo = (’cc’, ’-E’, $bar);

将 $bar 的 值 赋 给 $foo. 注 意 , 数 组 在 标 量 上 下 文 中 的 值 是 数 组 的 长 度 ; 下 例 将 3赋 给 $foo:

    @foo = (’cc’, ’-E’, $bar);
    $foo = @foo;                # $foo gets 3

列 表 的 最 后 可 以 输 入 逗 号 , 所 以 这 样 也 是 正 确 的 :

    @foo = (
        1,
        2,
        3,
    );

要 将 here-document 赋 给 数 组 , 一 行 作 为 一 个 元 素 , 可 以 这 样 作 :

    @sauces = <<End_Lines =~ m/(\S.*\S)/g;
        normal tomato
        spicy tomato
        green chile
        pesto
        white wine
    End_Lines

列 表 会 自 动 插 入 子 列 表 . 也 即 , 下 例 将 展 开 数 组 ,哈 希 等 , 并 将 其 中 的 每 一 个 元 素 作 为 该 新 列 表 的 一 个 元 素 . 数 组 或 哈 希 失 去 其 原 来 的 身 份 .列 表

    (@foo,@bar,&SomeSub,%glarch)

包 括 @foo,@bar的 每 一 个 元 素 ,包 括 函 数 SomeSub 返 回 值 列 表 的 每 一 个 元 素 , 包 括 %glarch 的 每 一 个 字 值 对 . 要 想 使 用 不 内 插 的 列 表 , 可 以 参 见 perlref

空 列 表 可 以 表 示 为 (). 在 列 表 中 插 入 空 列 表 没 有 意 义 . ((),(),()) 与 ()相 同 . 同 样 , 内 插 一 个 空 数 组 也 没 有 意 义 .

合 并 的 语 法 表 示 开 和 闭 括 号 都 是 可 选 的 (除 非 为 表 示 优 先 级 需 要 ); 而 列 表 可 以 以 可 选 的 逗 号 结 束 表 示 列 表 中 的 多 个 逗 号 是 合 法 的 语 法 。 列 表 "1,,3" 是 两 个 列 表 的 并 置 , "1," 还 有 3, 第 一 个 以 可 选 的 逗 号 结 束 。 "1,,3""(1,),(3)" 也 是 "1,3" (类 似 的 , "1,,,3""(1,),(,),3" 也 是 "1,3" 等 等 ) 不 过 我 们 不 建 议 你 使 用 这 么 混 乱 的 写 法

列 表 也 可 以 象 数 组 一 样 使 用 下 标 . 为 了 避 免 歧 义 需 要 在 列 表 外 使 用 括 号 . 例 如 :

    # Stat returns list value.
    $time = (stat($file))[8];
    # SYNTAX ERROR HERE.
    $time = stat($file)[8];  # OOPS, FORGOT PARENTHESES
    # Find a hex digit.
    $hexdigit = (’a’,’b’,’c’,’d’,’e’,’f’)[$digit-10];

    # A "reverse comma operator".
    return (pop(@foo),pop(@foo))[0];

可 以 给 列 表 赋 值 , 当 然 列 表 中 的 每 个 元 素 必 须 合 法 才 行 :

    ($a, $b, $c) = (1, 2, 3);

    ($map{’red’}, $map{’blue’}, $map{’green’}) = (0x00f, 0x0f0, 0xf00);

特 例 是 可 以 赋 值 为 "undef"。 当 忽 略 程 序 的 某 些 返 回 值 时 这 很 有 用 :

    ($dev, $ino, undef, undef, $uid, $gid) = stat($file);

列 表 赋 值 处 于 标 量 上 下 文 中 时 , 返 回 值 是 等 号 右 侧 的 表 达 式 的 元 素 个 数 :

    $x = (($foo,$bar) = (3,2,1));       # set $x to 3, not 2
    $x = (($foo,$bar) = f());           # set $x to f()’s return count

这 在 布 尔 上 下 文 中 很 方 便 , 因 为 多 数 列 表 函 数 在 结 束 时 返 回 空 列 表 , 这 时 列 表 赋 值 会 返 回 0, 被 解 释 为 FALSE.

它 也 是 一 个 有 用 的 习 惯 的 来 源 , 就 是 在 列 表 上 下 文 中 执 行 一 个 函 数 或 操 作 , 然 后 记 录 返 回 值 的 个 数 , 方 法 是 为 一 个 空 列 表 赋 值 , 然 后 在 标 量 上 下 文 中 使 用 这 个 值 。 例 如 , 如 下 代 码 :

    $count = () = $string =~ /\d+/g;

将 置 $count$string 中 找 到 的 数 字 组 数 量 。 这 样 能 行 的 原 因 是 模 式 匹 配 是 列 表 上 下 文 (因 为 它 被 赋 予 一 个 空 列 表 ), 因 此 返 回 所 有 匹 配 部 分 的 列 表 。 在 标 量 上 下 文 中 的 列 表 赋 值 将 它 转 换 为 元 素 的 个 数 (这 里 是 模 式 被 匹 配 的 数 量 ), 然 后 赋 值 给 $count。 注 意 简 单 地 使 用

    $count = $string =~ /\d+/g;

没 有 作 用 , 因 为 在 标 量 上 下 文 中 的 模 式 匹 配 只 会 返 回 true 或 false, 而 不 是 所 有 的 匹 配 。

最 后 一 个 元 素 可 以 是 数 组 或 哈 希 :

    ($a, $b, @rest) = split;
    my($a, $b, %rest) = @_;

当 然 可 以 在 任 何 位 置 使 用 数 组 或 哈 希 , 不 过 第 一 个 数 组 或 哈 希 会 将 所 有 的 值 都 据 为 己 有 , 其 它 的 元 素 都 会 变 为 undefined.这 在 my() 或 local()中 或 许 有 用 .

哈 希 可 以 用 含 有 字 值 对 的 列 表 来 初 始 化 :

    # same as map assignment above
    %map = (’red’,0x00f,’blue’,0x0f0,’green’,0xf00);

列 表 和 数 组 交 互 性 很 强 , 哈 希 则 不 然 . 你 可 以 象 使 用 数 组 时 一 样 对 列 表 使 用 下 标 并 不 意 味 着 可 以 象 使 用 哈 希 一 样 使 用 列 表 . 同 样 ,处 于 列 表 中 的 哈 希 总 是 以 字 值 对 的 形 式 展 开 . 因 此 有 时 使 用 引 用 要 更 好 一 些 .

通 常 在 字 值 对 中 使 用 "=>" 操 作 符 会 更 易 读 . "=>" 与 逗 号 作 用 相 同 , 不 过 它 还 有 一 个 作 用 , 那 就 是 可 以 使 它 左 侧 的 对 象 被 解 释 为 字 符 串 -- 如 果 该 对 象 是 裸 字 的 话 ,将 是 合 法 的 标 识 符 ("=>" 不 引 用 包 含 双 冒 号 的 复 合 标 识 符 ). 这 在 初 始 化 哈 希 时 棒 极 了 :

    %map = (
                 red   => 0x00f,
                 blue  => 0x0f0,
                 green => 0xf00,
   );

或 者 初 始 化 哈 希 的 引 用 :

    $rec = {
                witch => ’Mable the Merciless’,
                cat   => ’Fluffy the Ferocious’,
                date  => ’10/31/1776’,
    };

or for using call-by-named-parameter to complicated functions:

   $field = $query->radio_group(
               name      => ’group_name’,
               values    => [’eenie’,’meenie’,’minie’],
               default   => ’meenie’,
               linebreak => ’true’,
               labels    => \%labels
   );

注 意 哈 希 初 始 化 时 的 顺 序 和 输 出 时 的 顺 序 并 不 一 定 相 同 . 要 得 到 顺 序 的 输 出 可 以 参 见 perlfunc 中 的 "sort"

Subscripts 下 标

数 组 可 以 用 一 个 美 元 符 号 , 加 上 它 的 名 字 (不 包 括 前 导 的 "@"), 加 上 方 括 号 和 其 中 包 含 的 下 标 来 取 得 值 。 例 如 :

    @myarray = (5, 50, 500, 5000);
    print "Element Number 2 is", $myarray[2], "\n";

数 组 下 标 从 0 开 始 。 负 值 下 标 返 回 从 尾 部 开 始 数 的 值 。 在 我 们 的 例 子 中 , $myarray[−1] 将 是 5000, $myarray[−2] 是 500。

Hash 下 标 与 此 类 似 , 但 是 不 使 用 方 括 号 而 是 花 括 号 。 例 如 :

    %scientists =
    (
        "Newton" => "Isaac",
        "Einstein" => "Albert",
        "Darwin" => "Charles",
        "Feynman" => "Richard",
    );

    print "Darwin’s First Name is ", $scientists{"Darwin"}, "\n";

Slices 片 段

通 常 对 哈 希 或 数 组 一 次 访 问 一 个 元 素 . 也 可 以 使 用 下 标 对 列 表 元 素 进 行 访 问 .

    $whoami = $ENV{"USER"};             # one element from the hash
    $parent = $ISA[0];                  # one element from the array
    $dir    = (getpwnam("daemon"))[7];  # likewise, but with list

片 段 可 以 一 次 访 问 列 表 ,数 组 或 哈 希 中 的 几 个 元 素 , 这 是 通 过 列 表 下 标 来 实 现 的 . 这 比 分 别 写 出 每 个 值 要 方 便 一 些 .

    ($him, $her)   = @folks[0,-1];              # array slice
    @them          = @folks[0 .. 3];            # array slice
    ($who, $home)  = @ENV{"USER", "HOME"};      # hash slice
    ($uid, $dir)   = (getpwnam("daemon"))[2,7]; # list slice

既 然 可 以 给 列 表 赋 值 , 当 然 也 可 以 哈 希 或 数 组 的 片 段 赋 值 .

    @days[3..5]    = qw/Wed Thu Fri/;
    @colors{’red’,’blue’,’green’}
                   = (0xff0000, 0x0000ff, 0x00ff00);
    @folks[0, -1]  = @folks[-1, 0];

上 面 的 操 作 与 下 列 语 句 等 价 :

    ($days[3], $days[4], $days[5]) = qw/Wed Thu Fri/;
    ($colors{’red’}, $colors{’blue’}, $colors{’green’})
                   = (0xff0000, 0x0000ff, 0x00ff00);
    ($folks[0], $folks[-1]) = ($folks[-1], $folks[0]);

既 然 改 变 片 段 就 会 改 变 数 组 或 哈 希 的 原 始 值 , 那 么 "foreach" 结 构 可 以 部 分 或 全 部 地 改 变 数 组 或 哈 希 的 值 .

    foreach (@array[ 4 .. 10 ]) { s/peter/paul/ }

    foreach (@hash{qw[key1 key2]}) {
        s/^\s+//;           # trim leading whitespace
        s/\s+$//;           # trim trailing whitespace
        s/(\w+)/\u\L$1/g;   # "titlecase" words
    }

空 列 表 的 片 段 还 是 空 列 表 , 因 此 :

    @a = ()[1,0];           # @a has no elements
    @b = (@a)[0,1];         # @b has no elements
    @c = (0,1)[2,3];        # @c has no elements

但 是 :

    @a = (1)[1,0];          # @a has two elements
    @b = (1,undef)[1,0,2];  # @b has three elements

下 例 利 用 了 这 一 特 性 ,当 返 回 空 列 表 时 循 环 终 止 :

    while ( ($home, $user) = (getpwent)[7,0]) {
        printf "%-8s %s\n", $user, $home;
    }

我 们 在 前 面 说 过 , 标 量 上 下 文 中 的 列 表 赋 值 返 回 值 是 右 侧 的 元 素 个 数 . 空 列 表 没 有 元 素 , 所 以 当 口 令 文 件 读 完 后 , 返 回 值 是 0而 不 是 2.

为 什 么 对 哈 希 的 片 段 使 用 ’@’而 不 是 ’%’呢 . 因 为 括 号 的 类 型 (方 括 号 或 花 括 号 )决 定 了 它 是 数 组 还 是 哈 希 . 而 数 组 或 哈 希 的 开 始 字 符 (’$’或 ’@’)表 示 返 回 值 是 单 个 值 还 是 多 个 值 (列 表 ).

Typeglobs and Filehandles 全 局 类 型 和 文 件 句 柄

Perl 使 用 叫 做 全 局 类 型 的 类 型 来 支 持 整 个 符 号 表 项 . 全 局 类 型 的 前 缀 是 *, 因 为 它 表 示 所 有 的 类 型 . 这 在 过 去 通 常 用 来 给 函 数 传 递 数 组 或 哈 希 的 引 用 , 但 是 现 在 有 了 真 正 的 引 用 , 这 就 几 乎 不 需 要 了 .

现 在 ,全 局 类 型 的 主 要 用 途 是 创 建 符 号 表 别 名 . 如 下 赋 值 :

    *this = *that;

使 得 $this 成 为 $that的 别 名 , @this 成 为 @that的 别 名 ,%this 成 为 %that的 别 名 , &this 成 为 &that的 别 名 , 等 等 . 使 用 引 用 会 更 安 全 . 这 样 :

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

暂 时 使 $Here::blue 成 为 $There::green的 别 名 , 但 不 会 使 @Here::blue 成 为 @There::green的 别 名 , 也 不 会 使 %Here::blue 成 为 %There::green的 别 名 , 等 等 . 参 见 perlmod 中 的 Symbol Tables 有 多 个 例 子 . 看 起 来 可 能 有 些 怪 异 , 不 过 这 却 是 整 个 import/export系 统 的 基 础 .

全 局 类 型 的 其 它 用 途 还 有 , 给 函 数 传 输 文 件 句 柄 或 是 创 建 新 的 文 件 句 柄 . 如 果 你 要 使 用 全 局 类 型 代 替 文 件 句 柄 , 可 以 这 样 做 :

    $fh = *STDOUT;

或 者 使 用 真 正 的 引 用 , 象 这 样 :

    $fh = \*STDOUT;

参 见 perlsub 有 关 于 间 接 句 柄 的 多 个 例 子 .

全 局 类 型 也 是 使 用 local() 创 建 局 部 文 件 句 柄 的 一 种 方 法 . 作 用 范 围 在 当 前 块 之 内 , 但 是 可 以 被 传 回 .例 如 :

    sub newopen {
        my $path = shift;
        local  *FH;  # not my!
        open   (FH, $path)          or  return undef;
        return *FH;
    }
    $fh = newopen(’/etc/passwd’);

既 然 我 们 有 *foo{THING} 这 样 的 记 法 , 全 局 类 型 不 再 多 用 于 文 件 句 柄 ,但 在 从 函 数 传 出 或 向 函 数 传 入 新 的 文 件 句 柄 时 它 还 是 必 需 的 .因 为 *HANDLE{IO} 只 有 在 HANDLE 已 经 是 文 件 句 柄 时 才 起 作 用 . 换 言 之 , 在 建 立 新 符 号 表 项 时 必 须 使 用 *FH; *foo{THING} 是 不 行 的 . 不 知 道 该 用 谁 时 , 使 用 *FH

所 有 能 创 建 文 件 句 柄 的 函 数 (open(), opendir(), pipe(), socketpair(), sysopen(), socket(), 和 accept()) ,在 传 递 给 它 们 的 句 柄 是 标 量 时 ,会 自 动 创 建 一 个 匿 名 句 柄 . 这 使 得 象 open(my $fh, ...) 和 open(local $fh,...) 这 样 的 结 构 可 以 创 建 一 个 在 超 出 范 围 时 可 以 自 动 关 闭 的 句 柄 ,如 果 没 有 另 外 的 对 它 们 的 引 用 的 话 . 这 大 大 减 少 了 全 局 类 型 的 使 用 ,当 需 要 打 开 一 个 可 以 到 处 使 用 的 句 柄 时 , 可 以 这 样 做 :

    sub myopen {
        open my $fh, "@_"
             or die "Can’t open ’@_’: $!";
        return $fh;
    }

    {
        my $f = myopen("</etc/motd");
        print <$f>;
        # $f implicitly closed here
    }

注 意 如 果 使 用 了 初 始 化 的 标 量 , 那 么 结 果 会 有 不 同 : "my $fh=’zzz’; open($fh, ...)""open( *{’zzz’}, ...)" 等 价 。 "use strict ’refs’" 禁 止 了 这 样 做 。

另 一 个 创 建 匿 名 句 柄 的 方 法 是 用 Symbol 模 块 或 IO::Handle 模 块 或 诸 如 此 类 的 东 西 . These modules have the advantage of not hiding different types of the same name during the local(). 在 open() in the perlfunc manpage 的 文 末 有 个 例 子 .(译 者 注 :说 实 话 ,对 匿 名 句 柄 我 现 在 也 是 一 头 雾 水 ,翻 译 的 不 当 之 处 ,请 高 手 指 出 .)

SEE ALSO 参 见

参 见 the perlvar manpage 了 解 Perl的 内 建 变 量 和 合 法 变 量 。 参 见 the perlref manpage, the perlsub manpage, 和 Symbol Tables in the perlmod manpage 了 解 全 局 类 型 和 *foo{THING} 语 法 。

中 文 版 维 护 人

redcandle <redcandle51 [AT] nospam.com>

中 文 版 最 新 更 新

2001年 12月 4日 星 期 二

中 文 手 册 页 翻 译 计 划

http://cmpp.linuxforum.net