Manpages

NAME

perlform − Perl 格 式

DESCRIPTION 描 述

Perl的 一 些 内 部 机 制 、 可 以 帮 助 我 们 产 生 一 份 简 单 的 格 式 化 图 表 。 经 过 perl的 处 理 , 你 列 印 的 格 式 可 以 接 近 於 你 所 见 的 外 貌 。 它 可 以 记 录 如 你 现 在 正 处 在 哪 个 页 面 , 每 个 页 面 的 行 数 与 何 时 列 印 出 页 面 的 标 题 。 关 键 字 , format() 格 式 函 数 与 write()执 行 函 数 是 直 接 引 自 FORTRAN语 法 。 详 情 可 参 阅 perlfunc。 幸 运 的 是 列 印 的 格 式 可 读 性 又 有 所 提 高 。 几 乎 类 似 BASIC 的 PRINT USING。 可 以 把 它 想 象 为 简 单 的 nroff(1).

有 如 子 程 序 与 包 一 样 , 格 式 只 是 语 句 的 声 明 , 而 不 是 执 行 调 用 。 故 它 可 以 放 在 程 式 的 任 何 位 置 ( 一 般 最 好 是 把 它 们 集 中 在 一 块 ) 。 与 perl的 其 它 变 量 名 字 类 型 不 同 , 格 式 命 名 有 别 於 一 般 的 独 自 的 定 义 。 也 就 是 说 , 你 有 一 个 名 为 Foo的 函 数 , 它 与 另 一 个 格 式 名 称 为 Foo的 东 西 是 完 全 不 同 。 但 是 缺 省 的 格 式 名 称 与 有 关 连 的 文 件 句 柄 可 用 相 同 的 名 字 。 所 以 缺 省 的 输 出 格 式 名 称 STDOUT, 它 的 文 件 句 柄 名 称 就 是 STDOUT。 而 对 缺 省 格 式 名 称 TEMP, 它 的 文 件 句 柄 名 称 也 可 以 是 TEMP。 虽 然 名 称 一 样 但 两 者 并 不 相 同 。

输 出 格 式 的 语 法 如 下 :

    format NAME =
    FORMLIST
    .

如 省 略 格 式 名 称 , 格 式 名 称 将 以 标 准 输 出 STDOUT命 名 。 而 格 式 项 目 将 包 括 了 好 几 个 连 续 横 行 。 每 一 行 属 於 下 列 叁 种 型 态 之 一 :

1.

注 释 ( comment), 以 符 号 “#”置 於 每 行 的 开 头 。

2.

图 案 行 (picture line), 规 定 了 单 一 行 的 格 式 化 外 观 。

3.

参 数 行 , 提 供 一 些 数 值 以 对 应 前 面 的 图 案 行 。

图 案 行 的 输 出 效 果 就 与 我 们 看 到 的 一 样 , 除 了 某 些 值 域 栏 位 会 给 相 对 应 数 值 取 代 外 , 每 个 输 入 栏 位 都 以 一 个 @或 ^ 控 制 符 开 头 。 这 些 单 行 内 的 控 制 符 不 能 做 任 何 窜 改 取 代 (勿 与 数 组 变 量 @混 淆 )。 @栏 位 是 属 於 正 常 形 态 的 栏 位 , 而 ^栏 位 则 用 来 表 示 可 以 输 入 多 行 文 字 。 至 於 该 栏 位 则 由 < > 或 ⎪ 符 号 跟 随 其 後 指 定 向 左 、 右 、 或 居 中 对 齐 。 并 同 时 跟 据 该 符 号 的 数 目 , 输 入 指 定 资 料 的 长 度 。 如 变 量 内 容 超 过 限 定 长 度 、 格 式 列 印 时 会 自 动 删 除 多 馀 的 部 份 。

另 一 种 指 定 向 右 对 齐 方 式 , 是 使 用 #符 号 来 指 定 一 个 数 字 栏 位 。 如 此 可 方 便 小 数 点 定 位 。 如 果 输 入 值 里 还 包 含 一 个 换 行 字 元 (0, 则 仅 列 印 出 该 换 行 字 元 前 的 资 料 。 最 後 图 案 行 出 现 的 @*这 个 特 别 符 号 标 记 , 可 以 用 来 列 印 多 行 并 且 不 被 截 掉 的 数 值 。

接 下 来 的 一 行 、 是 跟 据 图 案 行 里 的 值 域 栏 位 输 入 相 应 的 数 值 。 如 果 是 利 用 运 算 式 提 供 数 值 的 话 、 必 须 以 逗 号 分 隔 。 因 为 所 有 的 表 示 法 都 会 被 当 成 一 个 串 连 内 容 再 行 处 理 。 所 以 一 个 单 一 的 串 列 表 示 法 也 可 产 生 多 个 串 列 资 料 。 如 果 表 示 法 是 利 用 括 号 围 起 , 可 能 会 展 开 好 几 行 。 若 想 如 是 安 排 , 第 一 行 的 第 一 个 单 字 必 须 是 以 左 括 号 开 始 。 如 果 运 算 式 内 有 小 数 点 的 数 字 类 型 须 要 处 理 、 同 时 图 案 行 的 相 关 符 号 也 指 出 小 数 位 须 列 印 出 来 (除 了 图 案 行 内 的 包 含 小 数 点 "."的 数 字 控 制 符 号 #外 )。 小 数 点 列 印 出 的 外 貌 , 以 当 地 的 运 行 版 本 决 定 (LC_NUMERIC locale)。 也 就 是 说 、 在 德 文 地 区 使 用 小 数 格 示 输 出 时 、 小 数 点 的 显 示 将 是 ","而 非 "."。 相 关 资 料 请 参 考 perllocale 与 "警 告 "

图 案 行 里 的 栏 位 如 果 以 ^控 制 符 开 头 、 格 式 将 会 作 特 殊 化 处 理 。 如 果 该 栏 位 是 注 解 栏 位 又 没 定 义 其 值 、 栏 位 将 以 空 白 取 代 。 若 是 其 它 型 态 、 则 视 为 一 种 填 补 资 料 的 状 态 。 在 此 、 我 们 不 能 随 便 填 入 任 意 表 示 法 进 去 。 相 反 、 必 须 以 相 关 的 变 量 输 入 字 串 内 容 。 perl会 尽 量 将 文 字 放 入 该 栏 位 、 然 後 把 字 串 的 前 面 部 份 删 去 。 当 你 下 次 使 用 该 字 串 变 量 时 、 可 以 使 用 後 面 的 字 串 部 份 (换 句 话 说 、 在 执 行 write函 数 时 、 字 串 变 量 的 内 容 是 会 改 变 的 )。 正 常 情 况 下 、 你 必 须 使 用 一 类 似 垂 直 状 的 堆 块 来 放 置 要 输 入 的 文 字 、 以 便 整 齐 列 印 出 一 柱 状 文 字 。 如 你 列 印 的 文 字 太 长 、 想 以 "..."取 代 过 长 的 文 字 时 、 你 可 以 藉 由 更 改 $: 变 量 值 来 取 代 分 隔 字 元 。 也 就 是 当 你 使 用 ENGLISH模 块 时 的 $FORMAT_LINE_BREAK_CHARACTERS的 意 思 。

使 用 ^符 号 栏 位 可 产 生 不 定 长 度 的 记 录 栏 位 。 如 果 要 列 印 的 文 字 很 短 、 你 想 压 缩 掉 文 字 後 的 空 白 、 请 在 想 压 缩 掉 的 空 白 地 方 加 上 一 个 "~"控 制 符 号 。 如 果 重 复 使 用 两 个 "~"符 号 、 则 该 行 会 被 重 复 列 印 、 直 到 该 栏 位 的 所 有 文 字 列 印 完 毕 为 止 (如 你 同 时 使 用 "@"值 域 栏 位 的 话 、 切 记 每 次 要 输 入 不 同 的 数 值 )。

列 印 格 示 标 题 的 缺 省 处 理 方 法 、 是 将 正 使 用 的 格 式 名 称 後 加 上 _TOP字 样 既 可 。 其 内 容 将 会 列 印 至 每 页 的 开 头 部 份 。 请 参 考 perlfunc/write 函 数

例 如 :

 # a report on the /etc/passwd file
 format STDOUT_TOP =
                         Passwd File
 Name                Login    Office   Uid   Gid Home
 ------------------------------------------------------------------
 .
 format STDOUT =
 @<<<<<<<<<<<<<<<<<< @⎪⎪⎪⎪⎪⎪⎪ @<<<<<<@>>>> @>>>> @<<<<<<<<<<<<<<<<<
 $name,              $login,  $office,$uid,$gid, $home
 .

 # a report from a bug report form
 format STDOUT_TOP =
                         Bug Reports
 @<<<<<<<<<<<<<<<<<<<<<<<     @⎪⎪⎪         @>>>>>>>>>>>>>>>>>>>>>>>
 $system,                      $%,         $date
 ------------------------------------------------------------------
 .
 format STDOUT =
 Subject: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
          $subject
 Index: @<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        $index,                       $description
 Priority: @<<<<<<<<<< Date: @<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
           $priority,        $date,   $description
 From: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
       $from,                         $description
 Assigned to: @<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
              $programmer,            $description
 ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                      $description
 ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                      $description
 ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                      $description
 ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                      $description
 ~                                    ^<<<<<<<<<<<<<<<<<<<<<<<...
                                      $description
 .

我 们 也 有 可 能 在 同 一 个 输 出 管 道 同 时 使 用 print 与 write函 数 。 但 使 用 时 、 必 须 修 改 $-的 特 殊 内 置 变 量 值 (使 用 English模 块 的 话 、 则 是 使 用 $FORMAT_LINES-LEFT变 量 )。

Format Variables 格 式 变 量

当 前 的 格 式 名 称 一 向 都 是 存 放 於 $~这 个 特 殊 变 量 内 ($FORMAT_NAME), 而 每 页 的 开 头 格 式 则 存 放 在 $^($FORMAT-TOP_NAME), 输 出 页 为 $%($FORMAT_PAGE_NUMBER), 每 页 行 数 是 $= ($FORMAT_LINE_PER_PAGE), 自 动 输 出 格 式 是 放 在 $⎪($OUTPUT_AUTOFLUSH)、 要 输 出 到 每 页 开 头 部 份 的 字 串 存 放 在 $^L ($FORMAT-FORMFEED)。 这 些 变 量 的 有 效 范 围 , 都 是 以 某 一 个 文 件 句 柄 为 单 元 。 因 此 、 你 必 须 调 用 select()函 数 来 调 用 适 当 的 文 件 句 柄 来 改 变 变 量 内 容 。

    select((select(OUTF),
            $~ = "My_Other_Format",
            $^ = "My_Top_Format"
           )[0]);

难 看 吧 ! 这 就 是 一 般 用 法 。 如 此 一 来 、 你 至 少 可 用 临 是 变 量 来 存 放 前 一 个 文 件 句 柄 。 事 实 上 、 这 已 是 较 好 的 作 法 , 除 了 可 读 性 提 高 外 、 也 提 供 你 一 个 位 置 暂 停 程 式 的 执 行 , 方 变 你 一 次 到 位 除 错 。

    $ofh = select(OUTF);
    $~ = "My_Other_Format";
    $^ = "My_Top_Format";
    select($ofh);

如 果 你 使 用 English模 块 , 你 甚 至 可 以 输 入 英 文 变 量 名 称

    use English ’-no_match_vars’;
    $ofh = select(OUTF);
    $FORMAT_NAME     = "My_Other_Format";
    $FORMAT_TOP_NAME = "My_Top_Format";
    select($ofh);

但 你 还 是 要 调 用 select()函 数 。 因 此 我 们 建 议 你 用 FileHandle模 块 。 现 在 你 可 用 小 写 英 文 字 母 的 格 式 名 称 来 处 理 这 些 特 殊 变 量 。

    use FileHandle;
    format_name     OUTF "My_Other_Format";
    format_top_name OUTF "My_Top_Format";

好 多 了 吧 !

NOTES

因 为 数 值 行 的 内 容 可 能 保 括 任 何 的 表 示 法 (我 们 指 的 是 @ 栏 位 而 非 ^ 栏 位 )。 因 此 你 可 使 用 其 它 函 数 、 建 立 更 加 复 杂 的 处 理 方 法 。 好 像 使 用 printf 函 数 、 或 自 己 定 义 的 函 数 。 列 如 :

    format Ident =
        @<<<<<<<<<<<<<<<
        &commify($n)
    .

在 栏 位 输 入 真 正 的 @ 或 ^符 号 :

    format Ident =
    I have an @ here.
            "@"
    .

将 整 行 字 置 中 对 齐 :

    format Ident =
    @⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪
            "Some text line"
    .

我 们 并 无 任 何 内 建 的 方 法 让 你 指 定 如 、 某 个 栏 位 要 对 齐 该 页 面 最 右 等 诸 如 此 类 事 项 。 但 你 仍 然 能 列 印 出 你 想 要 的 格 式 。 跟 据 目 前 页 面 直 行 数 目 , 调 用 eval()函 数 来 处 理 它 :

    $format  = "format STDOUT = \n"
             . ’^’ . ’<’ x $cols . "\n"
             . ’$entry’ . "\n"
             . "\t^" . "<" x ($cols-8) . "~~\n"
             . ’$entry’ . "\n"
             . ".\n";
    print $format if $Debugging;
    eval $format;
    die $@ if $@;

它 可 能 列 印 出 下 列 格 式 外 貌 :

 format STDOUT =
 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $entry
         ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
 $entry
 .

下 面 是 一 个 有 点 类 似 fmt(1)的 小 程 式 :

 format =
 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
 $_
 .

 $/ = ’’;
 while (<>) {
     s/\s*\n\s*/ /g;
     write;
 }

Footers 页 脚

虽 然 我 们 有 $FORMAT_TOP_NAME来 记 录 每 页 开 头 部 份 的 格 式 , 却 没 有 一 个 相 对 应 的 方 法 来 自 动 指 定 每 页 的 底 部 格 式 。 问 题 是 、 我 们 并 不 知 到 某 个 格 式 资 料 可 能 会 多 大 , 除 非 你 真 的 去 执 行 它 。 这 是 我 们 将 来 要 处 理 的 重 点 之 一 。

这 是 一 个 暂 时 的 应 用 方 案 如 果 你 有 一 个 固 定 大 小 的 页 脚 、 你 可 在 每 次 调 用 write函 数 前 检 查 变 量 $FORMAT_LINES_LEFT, 然 後 自 行 印 出 该 资 料 。

还 有 一 个 方 法 , 就 是 开 启 一 个 管 道 。 调 用 open(MYSELF,”⎪-”) (参 考 perlfunc/open() 函 数 )。 并 调 用 write函 数 把 资 料 输 往 MYSELF、 而 不 是 标 准 输 出 STDOUT。 然 後 利 用 子 串 列 的 标 准 输 入 、 来 重 新 处 理 每 页 开 头 或 结 尾 所 要 附 加 的 资 料 部 份 。 这 虽 不 方 便 , 但 还 是 可 办 到 的 。

Accessing Formatting Internals 格 式 处 理 的 核 心

至 於 低 阶 格 式 的 机 制 , 你 可 调 用 formlin()函 数 直 接 处 理 $^A变 量 ($ACCUMUNATOR)。

例 如 :

    $str = formline <<’END’, 1,2,3;
    @<<<  @⎪⎪⎪  @>>>
    END

    print "Wow, I just stored ’$^A’ in the accumulator!\n";

或 是 设 计 一 个 子 程 式 swrite()。 它 对 于 write 的 脚 色 相 当 于 sprint 对 于 print。

    use Carp;
    sub swrite {
        croak "usage: swrite PICTURE ARGS" unless @_;
        my $format = shift;
        $^A = "";
        formline($format,@_);
        return $^A;
    }

    $string = swrite(<<’END’, 1, 2, 3);
 Check me out
 @<<<  @⎪⎪⎪  @>>>
 END
    print $string;

WARNINGS 警 告

不 当 处 理 显 示 结 束 格 示 内 容 的 点 操 作 符 号 、 有 时 也 会 同 时 影 响 你 的 网 络 的 电 邮 功 能 (跟 据 过 往 经 验 、 错 误 是 必 然 而 不 能 避 免 )。 如 果 使 用 电 邮 输 出 格 式 内 容 、 你 应 先 处 理 好 结 束 格 式 点 操 作 符 位 置 。 切 勿 放 置 於 左 边 界 、 以 免 被 SMTP截 去 。

局 部 变 量 (引 用 ”my”定 义 变 量 )、 在 调 用 格 式 化 输 出 时 不 会 被 察 觉 。 除 非 在 使 用 局 部 变 量 的 串 程 内 另 行 定 义 (5.001版 本 前 并 没 有 局 部 变 量 一 词 )。

格 式 输 出 是 perl 语 言 里 维 一 受 制 於 编 程 使 用 地 区 的 部 分 。 如 果 当 前 的 使 用 地 区 使 用 LC_NUMERIC, 那 小 数 点 符 号 的 格 式 化 输 出 必 以 当 地 方 式 显 示 。 perl 不 会 理 会 当 地 的 所 须 格 式 , 除 非 你 调 用 了 use locale。 但 格 式 列 印 又 不 受 控 於 use locale。 因 为 locale 它 只 在 使 用 的 块 内 有 效 。 同 时 跟 据 历 史 原 因 、 格 式 的 作 用 域 不 仅 包 括 在 块 内 。 进 一 步 详 情 参 阅 perllocale 本 地 化 文 档 。

格 式 输 出 时 、 程 式 串 内 的 空 白 符 号 0,相 当 於 一 个 空 白 单 元 。 所 以 你 可 以 想 像 格 式 列 印 相 当 於 先 处 理 变 量 :

$value =~ tr/\n\t\f/ /; 将 强 制 性 另 印 新 行 。

除 非 图 案 行 已 定 义 、 馀 下 的 空 白 符 号

中 文 版 维 护 人

小 高   <you [AT] email.com>

中 文 版 最 新 更 新

2001年 12月 9日 星 期 日

中 文 手 册 页 翻 译 计 划

http://cmpp.linuxforum.net