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()中 或 許 \[u6709]用 .
哈 希 可 以 用 含 有 字 值 對 的 列 表 來 初 始 化 :
# 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日 星 期 二