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 警 告

不 當 處 理 顯 示 結 束 格 示 內 容 的 點 操 作 符 號 、 有 時 也 會 同 時 影 響 你 的 網 路 的 電 郵 功 \[u80FD](跟 據 過 往 經 驗 、 錯 誤 是 必 然 而 不 能 避 免 )。 如 果 使 用 電 郵 輸 出 格 式 內 容 、 你 應 先 處 理 好 結 束 格 式 點 操 作 符 位 置 。 切 勿 放 置 於 左 邊 界 、 以 免 被 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