目錄

名稱

perlport - 撰寫可攜式 Perl

描述

Perl 可在許多作業系統上執行。儘管大多數作業系統有很多共同點,但它們也具有各自獨特的功能。

本文件旨在幫助您了解何謂可攜式 Perl 代碼。這樣,一旦您決定撰寫可攜式代碼,您就知道畫出的界線在哪裡,並且可以在這些界線內進行操作。

在充分利用某一類型的計算機和利用整個範圍之間存在著一個權衡。自然地,隨著您擴大範圍並變

從另一個角度來看,編寫可移植代碼通常意味著有意限制你可以使用的選擇。當然,這需要紀律和犧牲。可移植性和便利性的乘積可能是一個常數。你已被警告。

請注意兩個重要點

並非所有 Perl 程序都需要是可移植的

沒有理由不使用 Perl 作為一種語言來將 Unix 工具粘合在一起,或者原型化一個 Macintosh 應用程序,或者管理 Windows 註冊表。如果在特定程序中出於某種原因或另一種原因,不追求可移植性是沒有意義的,那就不要煩惱了。

Perl 幾乎已經全部是可移植的

不要被誤導以為創建可移植的 Perl 代碼很難。事實並非如此。Perl 盡其所能地彌合了不同平台之間的差距,以及使用這些功能的所有手段。因此,幾乎所有的 Perl 代碼都可以在任何機器上運行而無需修改。但是在編寫可移植代碼時有一些重要的問題,而本文正是關於這些問題。

這是一個通則:當你面對一個通常使用整個平台範圍完成的任務時,考慮編寫可移植代碼。這樣,你不會因實現選擇而犧牲太多,同時還可以為用戶提供多種平台選擇。另一方面,當你必須利用某個特定平台的一些獨特功能時,這在系統編程中經常出現(無論是 Unix、Windows、VMS 等),請考慮編寫特定平台的代碼。

當代碼僅在兩個或三個操作系統上運行時,您可能只需要考慮這些特定系統的差異。重要的是要決定代碼將在哪里運行,並在您的決定上是有意識的。

以下材料分為三個主要部分:可移植性的主要問題("問題")、特定平台的問題("平台")以及在各種端口上行為不同的內置 Perl 函數實現("函數實現")。

這些信息不應被視為完整;它包括可能是短暫的關於一些端口的特異性的信息,其中幾乎所有都處於不斷發展的狀態。因此,這些材料應被視為一個永恒的進行中的工作(<IMG SRC="yellow_sign.gif" ALT="Under Construction">)。

問題

換行符

在大多數操作系統中,文件中的行以換行符結束。各個操作系統中使用的換行符可能有所不同。Unix 傳統上使用 \012,一種 DOS 风格的 I/O 使用 \015\012Mac OS 使用 \015,而 z/OS 使用 \025

Perl 使用 \n 來表示“邏輯”換行符號,其邏輯可能取決於使用的平台。在 MacPerl 中,\n 總是指 \015。在 EBCDIC 平台上,\n 可能是 \025\045。在 DOS 風格的 perls 中,\n 通常指 \012,但當以“文本”模式訪問文件時,perl 使用將其轉換為(或從中轉換)\015\012:crlf 層。取決於您是讀還是寫。Unix 在規範模式下的 tty 中也是這樣。\015\012 通常被稱為 CRLF。

要從文本行中刪除尾隨換行符號,請使用chomp。使用默認設置,該函數尋找尾隨的\n字符,因此以可移植的方式修剪。

在處理二進制文件(或以二進制模式處理的文本文件)時,請務必在使用$/之前明確設置適當值,以符合您的文件格式。

由於“文本”模式的轉換,DOS 風格的 perls 在以“文本”模式訪問文件時使用seektell存在限制。堅持只對從tell獲取的位置進行seek(而不是其他位置),通常可以自由地在“文本”模式下使用seektell。但是,使用seektell或其他文件操作可能不具有可移植性。然而,如果您對文件使用binmode,則通常可以安全地使用任意值進行seektell

在套接字編程中的一個常見誤解是,\n eq \012 到處都是相同的。當使用常見的 Internet 協議等協議時,專門要求使用\012\015,而邏輯\n\r(回車)的值不可靠。

print $socket "Hi there, client!\r\n";      # WRONG
print $socket "Hi there, client!\015\012";  # RIGHT

然而,使用\015\012(或\cM\cJ,或\x0D\x0A)可能會很繁瑣且難以看,對於維護代碼的人來說也會令人困惑。因此,Socket 模塊為那些希望的人提供了正確的東西。

use Socket qw(:DEFAULT :crlf);
print $socket "Hi there, client!$CRLF"      # RIGHT

當從套接字讀取時,請記住默認的輸入記錄分隔符$/\n,但是健壯的套接字代碼將識別為\012\015\012為行的結束。

while (<$socket>) {  # NOT ADVISABLE!
    # ...
}

因為CRLF和LF都以LF結尾,所以輸入記錄分隔符可以設置為LF,並稍後刪除任何CR。最好寫成

use Socket qw(:DEFAULT :crlf);
local($/) = LF;      # not needed if $/ is already \012

while (<$socket>) {
    s/$CR?$LF/\n/;   # not sure if socket uses LF or CRLF, OK
#   s/\015?\012/\n/; # same thing
}

這個例子比之前的更受青睞——即使對於 Unix 平台——因為現在任何 \015\cM)都會被去除(這樣很令人欣喜)。

同樣地,返回文本數據的函數——比如獲取網頁的函數——有時應該在返回數據之前轉換換行符,如果它們還沒有被轉換成本地的換行符表示。通常一行代碼就足夠了。

$data =~ s/\015?\012/\n/g;
return $data;

有些地方可能會讓人困惑。這裡有一個ASCII CR和LF字符的方便參考。你可以打印出來,放在你的錢包裡。

LF  eq  \012  eq  \x0A  eq  \cJ  eq  chr(10)  eq  ASCII 10
CR  eq  \015  eq  \x0D  eq  \cM  eq  chr(13)  eq  ASCII 13

         | Unix | DOS  | Mac  |
    ---------------------------
    \n   |  LF  |  LF  |  CR  |
    \r   |  CR  |  CR  |  LF  |
    \n * |  LF  | CRLF |  CR  |
    \r * |  CR  |  CR  |  LF  |
    ---------------------------
    * text-mode STDIO

Unix列假定你不是在規範模式下訪問串行線(如tty)。如果是的話,輸入時的CR變成 "\n",輸出時的 "\n" 變成 CRLF。

這些只是Perl中最常見的 \n\r 的定義。可能還有其他的。例如,在一個EBCDIC實現(例如z/OS(OS/390)或OS/400(使用ILE,PASE是基於ASCII的))上,上面的材料類似於“Unix”,但是代碼數字會改變。

LF  eq  \025  eq  \x15  eq  \cU  eq  chr(21)  eq  CP-1047 21
LF  eq  \045  eq  \x25  eq           chr(37)  eq  CP-0037 37
CR  eq  \015  eq  \x0D  eq  \cM  eq  chr(13)  eq  CP-1047 13
CR  eq  \015  eq  \x0D  eq  \cM  eq  chr(13)  eq  CP-0037 13

         | z/OS | OS/400 |
    ----------------------
    \n   |  LF  |  LF    |
    \r   |  CR  |  CR    |
    \n * |  LF  |  LF    |
    \r * |  CR  |  CR    |
    ----------------------
    * text-mode STDIO

數字的字節順序和寬度

不同的CPU以不同的順序(稱為 字節順序)和寬度(32位和64位是當今最常見的)存儲整數和浮點數。當程序嘗試將二進制格式的數字從一個CPU架構傳輸到另一個CPU架構時,通常會影響你的程序,通常是通過網絡連接“實時”進行,或者通過將數字存儲到二級存儲(如磁盤文件或磁帶)中。

相互衝突的存儲順序會使數字混亂不堪。如果一個小端主機(Intel,VAX)存儲 0x12345678(十進制為305419896),一個大端主機(Motorola,Sparc,PA)會將其讀取為 0x78563412(十進制為2018915346)。Alpha 和 MIPS 可以是:Digital/Compaq 在小端模式下使用/使用它們;SGI/Cray 在大端模式下使用它們。為了避免在網絡(socket)連接中出現此問題,請使用 packunpack 格式 nN,即“網絡”順序。這些是可移植的。

截至 Perl 5.10.0,你還可以使用 >< 修飾符來強制大端或小端字節順序。例如,如果你想存儲有符號整數或64位整數,這很有用。

您可以通過解壓縮以本機格式打包的數據結構來探索您平台的字節序。

print unpack("h*", pack("s2", 1, 2)), "\n";
# '10002000' on e.g. Intel x86 or Alpha 21064 in little-endian mode
# '00100020' on e.g. Motorola 68040

如果您需要區分字節序結構,可以使用以下任一變量設置:

$is_big_endian   = unpack("h*", pack("s", 1)) =~ /01/;
$is_little_endian = unpack("h*", pack("s", 1)) =~ /^1/;

不同寬度可能會導致截斷,即使在相同字節序的平台之間也是如此。寬度較小的平台會丟失數字的上部分。對於此問題沒有好的解決方案,除了避免傳輸或存儲原始二進制數字。

可以用兩種方式解決這兩個問題。要么始終以文本格式傳輸和存儲數字,而不是原始二進制,要么考慮使用模塊,如 Data::DumperStorable(自 Perl 5.8 起包含)。將所有數據都保存為文本會顯著簡化問題。

檔案與檔案系統

現今大多數平台都以層次結構的方式組織文件。因此,可以合理地假設所有平台都支持一個“路徑”的概念,以唯一標識系統上的文件。不過,實際上該路徑是如何寫的有很大差異。

儘管相似,文件路徑規範在 Unix、Windows、Mac OS、OS/2、VMS、VOS、RISC OS 等平台之間存在差異。例如,Unix 是少數具有單個根目錄的操作系統之一。

DOS、OS/2、VMS、VOS 和 Windows 可以像 Unix 一樣使用 / 作為路徑分隔符,或者使用自己特有的方式(例如具有多個根目錄和各種“非根”的設備文件,如 NIL: 和 LPT:)。

Mac OS 9 及之前版本使用 : 而不是 / 作為路徑分隔符。

文件系統可能既不支持硬鏈接(link)也不支持符號鏈接(symlinkreadlinklstat)。

檔案系統可能不支援存取時間戳記或更改時間戳記(這意味著唯一可攜式的時間戳記是修改時間戳記),或者時間戳記的秒數精度為一秒(例如,FAT 檔案系統將時間精度限制為兩秒)。

「inode 更改時間戳記」(-C 檔案測試)可能真的是「建立時間戳記」(在 Unix 中並非如此)。

VOS perl 可以模擬 Unix 檔案名稱,使用 / 作為路徑分隔符號。本機路徑名稱中的大於號、小於號、數字符號和百分比符號總是被接受。

RISC OS perl 可以模擬 Unix 檔案名稱,使用 / 作為路徑分隔符號,或者採用原生方式並使用 . 作為路徑分隔符號和 : 來表示檔案系統和磁碟名稱。

不要假設 Unix 檔案系統存取語義:讀取、寫入和執行是所有權限,而即使存在,它們的語義(例如在目錄上 rwx 代表什麼)也是 Unix 的。各種 Unix/POSIX 兼容性層通常會嘗試使像是 chmod 的介面正常運作,但有時根本沒有很好的對應。

File::Spec 模組提供了操作路徑規範並返回每個平台本機格式的方法。這通常是不必要的,因為 Perl 在每個支援的平台上都能理解 Unix 样式的路徑,但如果您需要為不了解 Unix 語法的本機工具產生本機路徑,或者如果您在未知(因此可能是本機)語法中操作路徑或路徑組件,File::Spec 是您的朋友。以下是兩個簡短的示例:

use File::Spec::Functions;
chdir(updir());        # go up one directory

# Concatenate a path from its components
my $file = catfile(updir(), 'temp', 'file.txt');
# on Unix:    '../temp/file.txt'
# on Win32:   '..\temp\file.txt'
# on VMS:     '[-.temp]file.txt'

通常,生產代碼不應該硬編碼文件路徑。將它們設為由使用者提供或從配置文件中讀取更好,請記住不同機器上的文件路徑語法有所不同。

這在像 Makefiles 和測試套件這樣的腳本中尤其顯著,它們通常假定 / 是子目錄的路徑分隔符號。

另一個有用的是標準發行版中的 File::Basename,它將路徑名稱分割為各部分(基本檔名、完整目錄路徑和檔案後綴)。

即使在單一平台上(如果你把Unix當作單一平台的話),也別指望特定系統文件或目錄的存在或內容,如/etc/passwd/etc/sendmail.conf/etc/resolv.conf/tmp/。例如,/etc/passwd可能存在但不包含加密密碼,因為系統正在使用某種形式的增強安全性。或者它可能不包含所有帳戶,因為系統正在使用NIS。如果程式碼確實需要依賴此類文件,請在程式碼的文檔中包含文件的描述和格式,然後讓用戶可以輕鬆覆蓋文件的默認位置。

不要假設文本文件會以換行符結尾。它們應該,但人們有時會忘記。

不要有兩個同名但大小寫不同的文件或目錄,如test.plTest.pl,因為許多平台具有大小寫不敏感(或至少是寬容大小寫)的文件名。此外,盡量避免在名稱中使用非單詞字符(除了.),並將它們保持在8.3的慣例中,以確保最大的可移植性,盡管這可能看起來負擔很重。

同樣,在使用AutoSplit模組時,盡量將您的函數保持為8.3命名和大小寫不敏感的慣例;或者,至少確保結果文件的前8個字符是唯一的(不區分大小寫)。

大多數系統都能容忍文件名中的空格,但並非所有系統都能容忍,在可能容忍空格的系統上,某些實用程序可能會因此而混淆。

許多系統(如DOS、VMS ODS-2)不能在文件名中使用超過一個.

不要假設>不會是文件名的第一個字符。始終使用open的三參數版本。

open my $fh, '<', $existing_file) or die $!;

兩參數的open是有魔力的,可以將字符(如><|)在文件名中翻譯,這通常是錯誤的。 sysopen和三參數的open就不會有這個問題。

不要在文件名中使用:,因為許多系統使用它來表示自己的語義(Mac OS Classic用於分隔路徑名組件,許多網絡方案和實用程序用於分隔節點名和路徑名等)。出於相同的原因,避免使用@;|

不要假設在路徑名稱中,您可以將兩個前置斜線//折疊成一個:一些網絡和集群文件系統對此有特殊語義。讓操作系統處理它。

根據ANSI C定義的可移植文件名字符

a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
. _ -

-不應該是第一個字符。如果你想要超正確,保持大小寫不敏感並且在8.3命名規則內(所有文件和目錄的名稱在.之前都必須在一個目錄中是唯一的,如果有的話,並且在.之後被截斷為三個字符,如果有的話)。 (並且不要在目錄名稱中使用.。)

系統交互

並非所有平台都提供命令行。這些通常是依賴於圖形用戶界面(GUI)進行用戶交互的平台。需要命令行界面的程序可能不會在所有地方都運行。這可能是程序的使用者要處理的問題,所以不要為此熬夜擔心。

一些平台無法刪除或重命名系統持有的文件,此限制也可能適用於更改文件系統元信息,如文件權限或所有者。記得在使用完畢後關閉文件。不要對打開的文件進行unlinkrename操作。不要對已經被綁定或打開的文件進行tieopen操作;先untieclose它。

不要同時多次打開同一個文件進行寫入,因為某些操作系統會對這些文件加上強制鎖。

不要假設在目錄上的寫入/修改權限就能在該目錄中添加或刪除文件/目錄。這取決於文件系統:在某些文件系統中,您還需要在文件/目錄本身擁有寫入/修改權限(甚至只需要)。在某些文件系統(AFS,DFS)中,添加/刪除目錄項目的權限是完全獨立的權限。

不要假設單個unlink就完全刪除了文件:某些文件系統(尤其是VMS中的文件系統)具有版本化文件系統,unlink僅刪除最新版本(它不會刪除所有版本,因為默認情況下這些平台上的本機工具也僅刪除最新版本)。刪除文件的所有版本的可移植用法是

1 while unlink "file";

如果由於某種原因(受保護,不存在等)文件無法刪除,則此操作將終止。

不要指望在 %ENV 中存在特定的環境變數。不要指望 %ENV 的項目區分大小寫,甚至保留大小寫。不要嘗試通過說 %ENV = (); 來清除 %ENV,或者,如果你真的需要,可以條件地使用 $^O ne 'VMS',因為在 VMS 中,%ENV 表比一個進程的鍵值字符串表多得多。

在 VMS 上,如果之前不存在,一些 %ENV 哈希中的項目在讀取時會動態創建。已知 $ENV{HOME}$ENV{TERM}$ENV{PATH}$ENV{USER} 的值是動態生成的。動態生成的特定名稱可能因 VMS 上 C 库的版本而異,可能存在比文檔記錄更多的名稱。

在 VMS 上,預設情況下,%ENV 哈希的更改在 perl 退出後仍然存在。同一進程中後續調用的 perl 可能會意外繼承本來應該是暫時的環境設置。

不要指望信號或 %SIG

不要指望文件名通配。使用 opendirreaddirclosedir 代替。

不要指望每個程序的環境變量,或每個程序的當前目錄。

不要指望 $! 的特定值,無論是數字還是字符串值。用戶可能更改其地區設置,導致錯誤消息被翻譯成他們的語言。如果你可以信賴 POSIXish 環境,你可以可移植地使用 Errno 模塊定義的符號,如 ENOENT。而且除了在系統調用失敗後立即之外,完全不要信賴 $! 的值。

命令名稱與文件路徑名稱

不要假設使用 systemexec 調用命令或程序的名稱也可以用來測試包含該命令或程序的可執行代碼的文件是否存在。首先,許多系統具有內部命令,這些命令內建於 shell 或操作系統中,雖然可以調用這些命令,但沒有相應的文件。其次,一些操作系統(例如,Cygwin、OS/2 和 VOS)對可執行文件有必需的後綴;這些後綴通常允許在命令名稱上,但不是必需的。因此,命令 perl 可能存在於名為 perlperl.exeperl.pm 的文件中,具體取決於操作系統。如果有的話,$Config{_exe} 變量在 Config 模塊中保存了可執行文件的後綴。第三,VMS 端仔細設置了 $^X$Config{perlpath},以便無需進一步處理。這樣做很好,因為下面使用的匹配正則表達式將不得不處理 VMS 文件名中可能的尾部版本號。

$^X 轉換成文件路徑名稱,考慮到各種作業系統的需求,請執行以下操作:

use Config;
my $thisperl = $^X;
if ($^O ne 'VMS') {
    $thisperl .= $Config{_exe}
        unless $thisperl =~ m/\Q$Config{_exe}\E$/i;
}

$Config{perlpath} 轉換成文件路徑名稱,請執行以下操作:

use Config;
my $thisperl = $Config{perlpath};
if ($^O ne 'VMS') {
    $thisperl .= $Config{_exe}
        unless $thisperl =~ m/\Q$Config{_exe}\E$/i;
}

網路

請不要假設您可以連接到公共互聯網。

請不要假設通過防火牆到達公共互聯網的方式只有一種。

請不要假設您可以通過除了 80 端口或某個網絡代理之外的任何端口連接到外部世界。許多防火牆會封鎖 ftp。

請不要假設您可以通過連接到本地 SMTP 端口來發送電子郵件。

請不要假設您可以通過名稱為 'localhost' 的任何節點或自身。對 '127.0.0.1' 也是如此。您將需要試試兩種方式。

請不要假設主機只有一張網卡,或者它不能綁定多個虛擬 IP 地址。

請不要假設特定的網絡設備名稱。

請不要假設特定的 ioctl 集將起作用。

請不要假設您可以 ping 主機並收到回覆。

請不要假設任何特定端口(服務)會回應。

請不要假設 Sys::Hostname(或任何其他 API 或命令)返回的是完全限定的主機名稱或非限定的主機名稱:一切取決於系統的配置方式。同樣請記住,對於 DHCP 和 NAT 等情況,您收到的主機名稱可能並不是非常有用。

上述所有的不要可能看起來令人生畏,而且確實如此,但關鍵是如果無法到達所需的特定網絡服務,要優雅地降級。報錯或者掛起看起來並不專業。

進程間通信(IPC)

一般來說,不要在旨在可移植的代碼中直接訪問系統。這意味著不要使用 systemexecforkpipe``qx//、帶有 |open,或者其他使得成為 Perl 駭客值得的事情。

在大多數平台上,一般都支援啟動外部處理程序的命令(雖然其中許多不支援任何形式的分叉)。使用它們的問題在於你在其上調用的對象。外部工具在不同平台上的命名通常不同,可能不在相同的位置上可用,可能接受不同的參數,行為可能不同,並且通常以與平台相關的方式呈現其結果。因此,你應該很少依賴它們來產生一致的結果。(不過,如果你在調用 netstat -a,你可能不期望它在 Unix 和 CP/M 上都運行。)

Perl 代碼中尤其常見的一個部分是打開一個管道來 sendmail

    open(my $mail, '|-', '/usr/lib/sendmail -t')
	or die "cannot fork sendmail: $!";

當知道 sendmail 可用時,這對於系統編程是沒有問題的。但對於許多非 Unix 系統甚至一些可能沒有安裝 sendmail 的 Unix 系統來說,這是不好的。如果需要一個可移植的解決方案,請參見 CPAN 上處理它的各種發行版。 Mail::MailerMail::SendMailTools 發行版中常用,提供幾種郵件方法,包括 mailsendmail 和直接 SMTP(通過 Net::SMTP)如果沒有郵件傳輸代理。 Mail::Sendmail 是一個獨立的模塊,提供簡單的、平台獨立的郵件。

Unix System V IPC(msg*()sem*()shm*())即使在所有 Unix 平台上也不可用。

不要使用 pack("N", 10, 20, 30, 40) 的裸結果或裸 v-strings(例如 v10.20.30.40)來表示 IPv4 地址:這兩種形式僅將四個字節打包成網絡順序。這將等於 C 語言 in_addr 結構體(這是套接字代碼內部使用的)並不保證。為了可移植性,請使用 Socket 模塊的例程,例如 inet_atoninet_ntoasockaddr_in

可移植代碼的經驗法則是:全部使用可移植 Perl 代碼,或使用一個模塊(可能內部使用特定平台的代碼實現,但提供一個通用的接口)。

外部子程序(XS)

XS 代碼通常可以在任何平台上運行,但依賴的庫、頭文件等可能不容易獲得或不具可移植性,或者 XS 代碼本身可能是特定平台的,就像 Perl 代碼可能是的一樣。如果庫和頭文件是可移植的,那麼通常確保 XS 代碼也是可移植的是合理的。

在編寫 XS 代碼時會出現不同類型的可移植性問題:端用戶系統上是否有 C 編譯器可用。C 本身帶有其自身的可移植性問題,而編寫 XS 代碼將使您面臨其中一些問題。純粹使用 Perl 編寫是實現可移植性的更簡單方法。

標準模組

一般而言,標準模組可跨平台使用。值得注意的例外包括 CPAN 模組(目前會連接到可能不可用的外部程序)、特定平台的模組(如 ExtUtils::MM_VMS)和 DBM 模組。

沒有一個 DBM 模組在所有平台上都可用。SDBM_File 和其他模組通常在所有 Unix 和 DOS 端口上都可用,但在 MacPerl 上不可用,只有 NDBM_File 和 DB_File 可用。

好消息是至少有一些 DBM 模組應該是可用的,而 AnyDBM_File 將使用它可以找到的任何模組。當然,這樣,代碼需要相當嚴格,下降到最大公因數(例如,每個記錄不超過 1K),以便它可以與任何 DBM 模組一起工作。詳細信息請參閱 AnyDBM_File。

時間和日期

系統對一天的時間和日曆日期的理解方式大不相同。不要假設時區存儲在 $ENV{TZ} 中,即使是這樣,也不要假設可以通過該變量控制時區。不要對三個字母的時區縮寫做出任何假設(例如 MST 可能是 Mountain Standard Time,但已知它代表莫斯科標準時間)。如果需要使用時區,請用一些不含糊的格式表示,例如從 UTC 偏移的確切分鐘數,或 POSIX 時區格式。

不要假設時代始於 1970 年 1 月 1 日 00:00:00,因為這是特定於操作系統和實現的。最好將日期存儲在一個明確的表示中。ISO 8601 標準將 YYYY-MM-DD 定義為日期格式,或者 YYYY-MM-DDTHH:MM:SS(這是一個文字 "T" 將日期與時間分開)。請使用 ISO 8601 而不是讓我們猜測日期 02/03/04 可能是什麼日期。ISO 8601 甚至可以直接排序。文本表示法(如 "1987-12-18")可以使用像 Time::Piece(參見 Time::Piece 中的 "Date Parsing")或 Date::Parse 這樣的模組輕鬆轉換為特定於操作系統的值。一個值陣列,例如由 localtime 返回的值,可以使用 Time::Local 轉換為特定於操作系統的表示。

當計算特定時間時,例如在時間或日期模組中進行測試時,計算時代的偏移量可能是合適的。

use Time::Local qw(timegm);
my $offset = timegm(0, 0, 0, 1, 0, 1970);

在Unix中,$offset的值將為0,但在Mac OS Classic中將是一個較大的數字。然後可以將$offset添加到Unix時間值中,以獲得任何系統上應該是正確的值。

字符集和字符編碼

盡量不要假設字符集方面的事情。

不要假設數值方面的任何事情(字符的ordchr)。不要使用明確的代碼點範圍(例如\xHH-\xHH)。但是,從Perl v5.22開始,使用正則表達式模式括號中的字符類範圍,如qr/[\N{U+HH}-\N{U+HH}]/是可移植的,從Perl v5.24開始,相同的範圍在tr///中也是可移植的。您可以可移植地使用符號字符類,例如[:print:]

不要假設字母字符是按照連續的方式編碼的(在數值上的意義)。可能存在間隙。但是,在Perl中的特殊編碼確保了qr/[A-Z]/qr/[a-z]/qr/[0-9]/的所有子集的行為都符合預期。對於這些範圍,tr///的行為也相同。在模式中,使用\N{...}記號指定終點的任何範圍都確保了字符集的可移植性,但是在Perl v5.22中,tr///並非如此,此問題在v5.24中修復了。

不要假設字符的排序方式。小寫字母可能在大寫字母之前或之後;小寫字母和大寫字母可能交錯,以便"a"和"A"都在"b"之前;重音和其他國際字符可能交錯,以便ä在"b"之前。可使用Unicode::Collate進行排序。

國際化

如果您可以假設POSIX(這是一個相當大的假設),則可以從perllocale中了解有關POSIX區域系統的更多信息。區域系統至少試圖使事情更具可移植性,或者至少對於非英語用戶來說更加便利和本地化友好。該系統影響字符集和編碼以及日期和時間格式等方面。

如果您真的想要國際化,應該考慮使用Unicode。有關更多信息,請參見perluniintroperlunicode

默認情況下,Perl假設您的源代碼是以8位ASCII超集編寫的。要在字符串和正則表達式中嵌入Unicode字符,您可以使用\x{HH}或(更可移植)\N{U+HH}表示法。您還可以使用utf8 pragma並將代碼編寫為UTF-8,這樣可以直接使用Unicode字符(不僅限於引號構造中,還可以用於標識符)。

系統資源

如果您的代碼將用於具有嚴重受限(或缺失!)虛擬內存系統的系統,那麼您應該特別注意避免浪費性的構造,例如

my @lines = <$very_large_file>;            # bad

while (<$fh>) {$file .= $_}                # sometimes bad
my $file = join('', <$fh>);                # better

最後兩個構造對大多數人來說可能看起來不直觀。第一個反覆增加一個字符串,而第二個則一次性分配了一大塊內存。在某些系統上,第二種方法比第一種更有效率。

安全性

大多數多用戶平台提供基本的安全性水平,通常在文件系統層面實現。但是,有些不幸的平台卻沒有。因此,在許多平台上,使用者ID、"家"目錄,甚至登錄狀態可能無法辨識。如果您撰寫注重安全性的程式,通常最好知道您將在哪種系統下運行,以便您可以明確為該平台(或平台類別)撰寫程式碼。

不要假設Unix文件系統訪問語義:操作系統或文件系統可能使用某些ACL系統,這些系統比通常的rwx更豐富。即使rwx存在,它們的語義可能不同。

(從安全性的角度來看,在嘗試執行某事之前測試權限是愚蠢的:如果嘗試這樣做,可能存在競態條件。在權限檢查和實際操作之間,有人或某物可能更改權限。儘管如此,請嘗試執行操作。)

不要假設Unix使用者和群組的語義:尤其是,不要期望$<$>(或$($))能夠用於切換身份(或成員身份)。

不要假設set-uid和set-gid的語義。(即使您這樣做了,也要三思:set-uid和set-gid是已知的安全漏洞。)

風格

在必須使用特定平台代碼的情況下,請考慮將特定平台代碼保留在一個地方,以使移植到其他平台更容易。使用Config模組和特殊變量$^O來區分平台,如"平台"中所述。

注意"else綜合症"

if ($^O eq 'MSWin32') {
  # code that assumes Windows
} else {
  # code that assumes Linux
}

else分支應該用於真正的最終後備,而不是用於特定於某些平台的代碼。

在提供模組或程序的測試時要小心。模組代碼可能是完全可移植的,但其測試可能不是。當測試產生其他進程或調用外部程序以幫助測試時,或者當(如上所述)測試假設某些關於文件系統和路徑的事情時,通常會發生這種情況。請務必不要依賴於特定的錯誤輸出樣式,例如在檢查失敗的系統調用後檢查$!。除了將其顯示為輸出之外,使用$!進行其他任務是值得懷疑的(儘管可以參考Errno模組以相對可移植地測試錯誤值)。一些平台期望某種輸出格式,並且在這些平台上調整了Perl。最具體地說,不要在測試錯誤值時將正則表達式錨定。

CPAN 測試人員

上傳到 CPAN 的模組會由不同平台的各種志願者進行測試。這些 CPAN 測試者會收到郵件通知每次新的上傳,並以 PASS、FAIL、NA(對該平台不適用)、或 UNKNOWN(未知)的回覆回覆列表,並附上任何相關的註記。

測試的目的是雙重的:一方面,幫助開發者修復由於缺乏其他平台測試而出現的問題;另一方面,提供用戶有關於某個模組在特定平台上是否運作的資訊。

另見

平台

Perl 是使用一個 $^O 變數構建的,該變數指示了它所構建的操作系統。這是為了幫助加速那些原本需要 use Config 並使用 $Config{osname} 值的代碼。當然,要獲取有關系統的更詳細信息,建議查看 %Config

然而,不能始終信任 %Config,因為它是在編譯時構建的。如果 Perl 是在一個地方構建的,然後轉移到另一個地方,有些值可能是錯誤的。這些值甚至可能是事後編輯過的。

Unix

Perl 可以在各種各樣的 Unix 和類 Unix 平台上運行(參見源代碼套件中的 hints/ 目錄中的大多數文件)。在這些系統中,$^O 的值(因此也是 $Config{osname} 的值)通常是通過在 shell 提示符下輸入 uname -a(或類似的命令)返回的字符串的第一個字段轉換為小寫並去除標點符號,或者通過測試文件系統以確定是否存在唯一命名的文件,如內核或標頭文件。以下是一些較受歡迎的 Unix 版本

uname         $^O        $Config{archname}
--------------------------------------------
AIX           aix        aix
BSD/OS        bsdos      i386-bsdos
Darwin        darwin     darwin
DYNIX/ptx     dynixptx   i386-dynixptx
FreeBSD       freebsd    freebsd-i386
Haiku         haiku      BePC-haiku
Linux         linux      arm-linux
Linux         linux      armv5tel-linux
Linux         linux      i386-linux
Linux         linux      i586-linux
Linux         linux      ppc-linux
HP-UX         hpux       PA-RISC1.1
IRIX          irix       irix
Mac OS X      darwin     darwin
NeXT 3        next       next-fat
NeXT 4        next       OPENSTEP-Mach
openbsd       openbsd    i386-openbsd
OSF1          dec_osf    alpha-dec_osf
reliantunix-n svr4       RM400-svr4
SCO_SV        sco_sv     i386-sco_sv
SINIX-N       svr4       RM400-svr4
sn4609        unicos     CRAY_C90-unicos
sn6521        unicosmk   t3e-unicosmk
sn9617        unicos     CRAY_J90-unicos
SunOS         solaris    sun4-solaris
SunOS         solaris    i86pc-solaris
SunOS4        sunos      sun4-sunos

因為 $Config{archname} 的值可能取決於硬件架構,所以它的變化可能比 $^O 的值更大。

DOS 及其衍生版本

Perl 一直被移植到運行在像 PC-DOS、MS-DOS、OS/2 以及大多數你能提到的 Windows 平台之下的 Intel 風格微型計算機上(如果你算上的話,除了 Windows CE)。熟悉 COMMAND.COM 或 CMD.EXE 樣式的用戶應該意識到每個文件規範可能存在微妙的差異。

my $filespec0 = "c:/foo/bar/file.txt";
my $filespec1 = "c:\\foo\\bar\\file.txt";
my $filespec2 = 'c:\foo\bar\file.txt';
my $filespec3 = 'c:\\foo\\bar\\file.txt';

系統調用接受 / 或 \ 作為路徑分隔符。然而,許多 DOS 時代的命令行實用程序將 / 視為選項前綴,因此可能會對包含 / 的文件名感到困惑。除了調用任何外部程序外,/ 將正常工作,而且可能更好,因為它更符合流行的用法,並避免了記住何時使用反斜杠和何時不使用的問題。

DOS FAT 文件系統只能容納 "8.3" 格式的文件名。在“不區分大小寫但保留大小寫”的 HPFS(OS/2)和 NTFS(NT)文件系統下,您可能需要注意像 readdir 函數返回的大小寫,或者與 openopendir 等函數一起使用的大小寫。

DOS 還將幾個文件名視為特殊文件名,例如 AUX、PRN、NUL、CON、COM1、LPT1、LPT2 等等。不幸的是,有時即使包含明確的目錄前綴,這些文件名也無法正常工作。如果您希望您的代碼可移植到 DOS 及其衍生產品,最好避免這些文件名。很遺憾,很難知道這些文件名的全部。

這些操作系統的用戶還可能希望使用腳本,例如 pl2bat.bat 來將包裹放在您的腳本周圍。

新行(\n)在從文件讀取和寫入時被 I/O 系統翻譯為 \015\012(請參見"換行符")。binmode($filehandle) 將保持 \n 為該文件句柄翻譯為 \012。對於處理二進制數據的代碼,應始終使用 binmode。這假設您事先意識到您的數據是二進制的。通用程序通常不應假設有關其數據的任何信息。

$^O 變量以及各種 DOS 相關 perl 的 $Config{archname} 值如下:

OS             $^O       $Config{archname}  ID    Version
---------------------------------------------------------
MS-DOS         dos       ?
PC-DOS         dos       ?
OS/2           os2       ?
Windows 3.1    ?         ?                  0     3 01
Windows 95     MSWin32   MSWin32-x86        1     4 00
Windows 98     MSWin32   MSWin32-x86        1     4 10
Windows ME     MSWin32   MSWin32-x86        1     ?
Windows NT     MSWin32   MSWin32-x86        2     4 xx
Windows NT     MSWin32   MSWin32-ALPHA      2     4 xx
Windows NT     MSWin32   MSWin32-ppc        2     4 xx
Windows 2000   MSWin32   MSWin32-x86        2     5 00
Windows XP     MSWin32   MSWin32-x86        2     5 01
Windows 2003   MSWin32   MSWin32-x86        2     5 02
Windows Vista  MSWin32   MSWin32-x86        2     6 00
Windows 7      MSWin32   MSWin32-x86        2     6 01
Windows 7      MSWin32   MSWin32-x64        2     6 01
Windows 2008   MSWin32   MSWin32-x86        2     6 01
Windows 2008   MSWin32   MSWin32-x64        2     6 01
Windows CE     MSWin32   ?                  3
Cygwin         cygwin    cygwin

各種 MSWin32 Perl 可通過從 Win32::GetOSVersion() 返回的列表的第五個元素的值來區分它們正在運行的操作系統。例如:

if ($^O eq 'MSWin32') {
    my @os_version_info = Win32::GetOSVersion();
    print +('3.1','95','NT')[$os_version_info[4]],"\n";
}

還有 Win32::IsWinNT()|Win32/Win32::IsWinNT(), Win32::IsWin95()|Win32/Win32::IsWin95(),以及 Win32::GetOSName(); 試試看 perldoc Win32。非常通用的 POSIX::uname() 也可以使用

c:\> perl -MPOSIX -we "print join '|', uname"
Windows NT|moonru|5.0|Build 2195 (Service Pack 2)|x86

Winsock 函數設置的錯誤現在直接放入 $^E,相關的 WSAE* 錯誤代碼現在從 ErrnoPOSIX 模組中導出以進行測試。

自從 Perl 5.20.0 以來,將錯誤(轉換為 POSIX 風格的 E* 錯誤代碼)放入 $! 的先前行為存在錯誤,因為具有相同名稱的 Winsock 和 POSIX 錯誤常量之間的非等價性,這種關係自 Perl 5.8.0 以來不幸地以某種方式建立。

新的行為為檢查可攜式軟件中的 Winsock 錯誤提供了更穩健的解決方案,而不會意外地匹配用於其他操作系統並且對 Winsock 有不同含義的 POSIX 測試。

舊的行為目前保留不變,包括所有的缺陷,以確保向後兼容性,但鼓勵用戶更改任何對 $! 測試的代碼,以匹配 $^E 測試以匹配 WSAE* 常量的 Winsock 錯誤。在適當的棄用期之後,從 Perl 5.24 開始,舊的行為可能會被移除,使得在 Winsock 函數調用後保持 $! 不變,以避免對要檢查的錯誤變量產生任何可能的混淆。

另見

VMS

Perl 在 VMS 上的討論請參閱 Perl 發行版中的 perlvms

截至撰寫本文時,VMS 的官方名稱是 OpenVMS。

從 Digital Command Language (DCL) shell 與 Perl 進行交互通常需要不同於 Unix shell 的引號。例如

$ perl -e "print ""Hello, world.\n"""
Hello, world.

如果您有興趣,可以使用幾種方式將您的 Perl 腳本包裝在 DCL .COM 文件中。例如

$ write sys$output "Hello from DCL!"
$ if p1 .eqs. ""
$ then perl -x 'f$environment("PROCEDURE")
$ else perl -x - 'p1 'p2 'p3 'p4 'p5 'p6 'p7 'p8
$ deck/dollars="__END__"
#!/usr/bin/perl

print "Hello from Perl!\n";

__END__
$ endif

如果您的 Perl-in-DCL 腳本希望執行像 $read = <STDIN>; 之類的操作,請注意使用 $ ASSIGN/nolog/user SYS$COMMAND: SYS$INPUT

VMS 操作系統有兩個文件系統,通過它們在磁盤上的結構(ODS)級別進行標識:ODS-2 及其後繼者 ODS-5。對 Perl 到 VMS 的初始移植早於 ODS-5,但所有當前的測試和開發都假設 ODS-5 及其功能,包括保留大小寫、文件規格中的擴展字符以及長達 8192 字節的名稱。

在 VMS 上,Perl 可以接受以下兩種格式的檔案規格:VMS 格式或 Unix 格式,如下所示。

$ perl -ne "print if /perl_setup/i" SYS$LOGIN:LOGIN.COM
$ perl -ne "print if /perl_setup/i" /sys$login/login.com

但不能混合使用兩者,如下所示。

$ perl -ne "print if /perl_setup/i" sys$login:/login.com
Can't open sys$login:/login.com: file specification syntax error

一般而言,實現可移植性的最簡單方式始終是以 Unix 格式指定檔案名稱,除非它們需要被原生命令或工具處理。基於後一考量,File::Spec 模組默認返回原生格式規格,不論輸入格式為何。可以通過在環境中指定 DECC$FILENAME_UNIX_REPORT 功能邏輯名稱,將此默認值反轉,以便始終以 Unix 格式報告檔案名稱。

在 VMS 格式的檔案規格中,檔案類型或擴展名始終存在,即使它的長度為零。這意味著,默認情況下,readdir 將在沒有擴展名的檔案後返回一個尾隨點,因此,在 Unix 中看到的是 "a",在 VMS 中則是 "a."。但是,可以通過在環境中啟用 DECC$READDIR_DROPDOTNOTYPE 功能來抑制尾隨點(請參閱 CRTL 文檔中的功能邏輯名稱)。

\n 代表的內容取決於所打開檔案的類型。它通常代表 \012,但也可能是 \015、\012、\015\012、\000、\040 或無,具體取決於檔案組織和記錄格式。VMS::Stdio 模組提供對具有不尋常屬性的檔案的特殊 fopen() 要求的訪問權限。

在 OpenVMS 上,$^O 的值為 "VMS"。要確定正在運行的架構,請參考 $Config{archname}。

在 VMS 上,Perl 從 SYS$TIMEZONE_DIFFERENTIAL 邏輯名稱中獲取 UTC 偏移量。儘管 VMS 的紀元始於 1858 年 11 月 17 日 00:00:00.00,但對 localtime 的調用被調整為從 1970 年 1 月 1 日 00:00:00.00 開始計算偏移量,就像 Unix 一樣。

另見

VOS

在 VOS(又稱 OpenVOS)上的 Perl 請參閱 Perl 發行版中的 README.vos(安裝為 perlvos)。Perl 在 VOS 上可以接受以下兩種格式的檔案規格:VOS 格式或 Unix 格式,如下所示。

$ perl -ne "print if /perl_setup/i" >system>notices
$ perl -ne "print if /perl_setup/i" /system/notices

甚至可以混合使用兩者,如下所示。

$ perl -ne "print if /perl_setup/i" >system/notices

儘管 VOS 允許斜杠字符出現在對象名稱中,但由於 VOS 版本的 Perl 解釋它為路徑名分隔字符,因此包含斜杠字符的 VOS 檔案、目錄或連結的名稱無法處理。這類檔案必須在被 Perl 處理之前重新命名。

在 OpenVOS Release 17.0 之前的舊版 VOS 中,檔案名稱限制為 32 個或更少字元,禁止檔案名稱以 - 字元開頭,並且禁止檔案名稱包含 (空格)或任何來自集合 !#%&'()*;<=>? 的字元。

在 OpenVOS Release 17.0 或更新版本中,支援一個名為擴展名的功能。在這些版本中,檔案名稱可以包含最多 255 個字元,禁止以 - 字元開頭,並且被禁止的字元集合減少為 #%*<>?。有涉及到空格和撇號的限制:這些字元不能開頭或結尾,也不能立即在句號之前或之後。此外,一個空格不能立即在另一個空格或連字符之前。具體來說,以下字元組合是禁止的:空格-空格、空格-連字符、句號-空格、空格-句號、句號-撇號、撇號-句號、前導或尾隨空格、前導或尾隨撇號。雖然擴展檔案名稱限制為 255 個字元,但路徑名稱仍限制為 256 個字元。

VOS 上的 $^O 的值為 "vos"。要確定正在運行的架構,請參考 $Config{archname}

另見

EBCDIC 平台

v5.22 核心 Perl 可在 z/OS(前身為 OS/390)上運行。理論上,它也可以在 AS/400 小型計算機上的 OS/400 的後續版本、以及 VM/ESA 和 S/390 主機上的 BS2000 上運行。這些計算機在內部使用 EBCDIC 字元集(通常用於 OS/400 的字符代碼集 ID 為 0037,而對於 S/390 系統則為 1047 或 POSIX-BC)。

此部分其餘內容可能需要更新,但我們不知道應該說什麼。請將評論提交至https://github.com/Perl/perl5/issues

在主機 Perl 目前運行於 "Unix 系統服務 for OS/390"(前身為 OpenEdition)、VM/ESA OpenEdition 或 BS200 POSIX-BC 系統(Perl 5.6 及以上版本支持 BS2000)。詳細信息請參見perlos390。請注意,對於 OS/400,也有一個 Perl 5.8.1/5.10.0 或更高版本的 PASE 移植版,該版本是基於 ASCII 的(與基於 EBCDIC 的 ILE 相反),請參見perlos400

截至 USS for OS/390 的 R2.5 版和 VM/ESA 的版本 2.3,這些 Unix 子系統不支持使用 #! shebang 對腳本進行調用。因此,在 OS/390 和 VM/ESA 上,Perl 腳本可以使用以下簡單腳本標頭執行

: # use perl
    eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
        if 0;
#!/usr/local/bin/perl     # just a comment really

print "Hello from perl!\n";

OS/390 將在版本 2.8 及更高版本中支持 #! shebang 語法。在所有 S/390 系統上,對system 和反引號的調用都可以使用 POSIX shell 語法。

在 AS/400 上,如果 PERL5 在您的庫清單中,您可能需要將 Perl 腳本包裝在 CL 程序中以像這樣調用它們

BEGIN
  CALL PGM(PERL5/PERL) PARM('/QOpenSys/hello.pl')
ENDPGM

這將在 QOpenSys 檔案系統的根目錄中調用 Perl 腳本 hello.pl。在 AS/400 上,對system 或反引號的調用必須使用 CL 語法。

在這些平台上,請注意 EBCDIC 字符集可能會影響某些 Perl 函數的操作(例如chrpackprintprintfordsortsprintfunpack),以及使用^&| 等運算符進行 ASCII 常量的位操作,更不用說處理與 ASCII 計算機的套接字界面(參見"換行符")。

幸運的是,大多數主機的 Web 伺服器將正確地將以下語句中的 \n 轉換為其 ASCII 等價物(在 Unix 和 z/OS 下 \r 是相同的)

print "Content-type: text/html\r\n\r\n";

在某些平台上,$^O 的值包括

uname         $^O        $Config{archname}
--------------------------------------------
OS/390        os390      os390
OS400         os400      os400
POSIX-BC      posix-bc   BS2000-posix-bc

用於確定是否在 EBCDIC 平台上運行的一些簡單技巧可能包括以下任何一項(也許是全部)

if ("\t" eq "\005")  { print "EBCDIC may be spoken here!\n"; }

if (ord('A') == 193) { print "EBCDIC may be spoken here!\n"; }

if (chr(169) eq 'z') { print "EBCDIC may be spoken here!\n"; }

您可能不希望依賴 EBCDIC 編碼的標點符號字符,因為這些字符可能因代碼頁而異(一旦您的模塊或腳本被傳聞與 EBCDIC 配合使用,人們就希望它能與所有 EBCDIC 字符集配合使用)。

另見

Acorn RISC OS

因為 Acorn 使用 ASCII 和新行 (\n) 在文本文件中作為 \012,像 Unix 一樣,並且因為 Unix 文件名仿真默認情況下已打開,大多數簡單的腳本可能會 "開箱即用"。原生文件系統是模塊化的,個別文件系統可以是區分大小寫或不區分大小寫的,通常是保留大小寫的。一些原生文件系統有名稱長度限制,將文件和目錄名稱默默地截斷以適應。腳本應注意,標準文件系統目前的名稱長度限制為 10 個字符,在一個目錄中最多有 77 個項目,但其他文件系統可能不會強加此類限制。

原生文件名的格式為

Filesystem#Special_Field::DiskName.$.Directory.Directory.File

其中

Special_Field is not usually present, but may contain . and $ .
Filesystem =~ m|[A-Za-z0-9_]|
DsicName   =~ m|[A-Za-z0-9_/]|
$ represents the root directory
. is the path separator
@ is the current directory (per filesystem but machine global)
^ is the parent directory
Directory and File =~ m|[^\0- "\.\$\%\&:\@\\^\|\177]+|

默認的文件名轉換大致為 tr|/.|./|,交換點和斜杠。

請注意 "ADFS::HardDisk.$.File" ne 'ADFS::HardDisk.$.File',並且如果腳本不小心,正則表達式中的第二階段 $ 插值將違反 $. 變量。

也允許由包含逗號分隔搜索列表的系統變量指定的邏輯路徑;因此,System:Modules 是有效的文件名,並且文件系統將使用 System$Path 的每個部分前綴 Modules,直到生成指向磁盤上對象的名稱。只有當 System$Path 包含單個項目列表時,才允許將新文件寫入 System:Modules。如果封裝在角括號中,文件系統還將擴展文件名中的系統變量,因此 <System$Dir>.Modules 將尋找文件 $ENV{'System$Dir'} . 'Modules'。這顯然意味著 完全限定的文件名可以以 <> 開頭,並且應始終使用 open 的三個參數形式。

因為 . 用作目錄分隔符號,且在 10 個字符後無法假設文件名是唯一的,Acorn 實現了 C 編譯器以從源代碼中指定的文件名中去除尾隨的 .c .h .s.o 後綴,並將相應的文件存儲在以後綴命名的子目錄中。因此,文件被轉換

foo.h           h.foo
C:foo.h         C:h.foo        (logical path variable)
sys/os.h        sys.h.os       (C compiler groks Unix-speak)
10charname.c    c.10charname
10charname.o    o.10charname
11charname_.c   c.11charname   (assuming filesystem truncates at 10)

Unix 模擬庫將文件名轉換為本機文件名的方式假設需要這種類型的轉換,並且允許用戶定義已知後綴的列表,進行這種類型的轉置。這可能看起來是透明的,但請考慮按照這些規則,foo/bar/baz.hfoo/bar/h/baz 都映射到 foo.bar.h.baz,並且 readdirglob 不能且不試圖模擬反向映射。文件名中的其他 . 被轉換為 /

如上所述,通過 %ENV 訪問的環境是全局的,並且約定是特定於程序的環境變量的形式是 Program$Name。每個文件系統都維護一個當前目錄,當前文件系統的當前目錄是 全局 當前目錄。因此,社交性程序不會更改當前目錄,而是依賴完整的路徑名,而程序(和 Makefiles)不能假設它們可以生成可以更改當前目錄而不影響其父目錄(以及其他所有人)的子進程。

因為本機操作系統文件處理程序是全局的,並且當前從 255 開始分配,0 是保留值,Unix 模擬庫模擬了 Unix 文件處理程序。因此,您不能依賴將 STDINSTDOUTSTDERR 傳遞給您的子程序。

用戶希望在未引用的情況下在命令行中表達形如 <Foo$Dir>.Bar 的文件名,這也會引起問題:`` 命令輸出捕獲必須進行猜測遊戲。它假設字符串 <[^<>]+\$[^<>]> 是對環境變量的引用,而涉及 <> 的任何其他內容都是重定向,並且通常能夠正確 99%。當然,問題在於腳本不能依賴於任何 Unix 工具是否可用,或者找到的任何工具是否具有類 Unix 的命令行參數。

在理論上,任何人都可以使用免費工具構建擴展和 XS。實際上,許多人沒有這麼做,因為 Acorn 平台的用戶習慣於二進制分發。MakeMaker 確實運行,但目前沒有可用的 make 能夠處理 MakeMaker 的 makefiles;即使在應該修復此問題的情況下,缺乏類 Unix 的 shell 也會導致 makefile 規則出現問題,尤其是形式為 cd sdbm && make all 的行,以及任何使用引用的內容。

"RISC OS" 是操作系統的正式名稱,但在 $^O 中的值是 "riscos"(因為我們不喜歡喊叫)。

其他的 Perl 版本

Perl 已經移植到許多不適合以上類別的平台上。其中一些,如 AmigaOS、QNX、Plan 9 和 VOS,已經被很好地整合到標準 Perl 源代碼套件中。您可能需要查看 CPAN 上的 ports/ 目錄以獲取有關信息,以及可能的二進制文件,例如:aos、Atari ST、lynxos、riscos、Novell Netware、Tandem Guardian,等等。(是的,我們知道這些操作系統中的一些可能屬於 Unix 類別,但我們不是標準組織。)

一些大約的操作系統名稱及其在 "其他" 分類中的 $^O 值包括

OS            $^O        $Config{archname}
------------------------------------------
Amiga DOS     amigaos    m68k-amigos

另請參見

功能實現

以下列出的是完全未實現或在各種平台上以不同方式實現的函數。在每個描述之前將是一個括號中的平台列表,說明描述適用的平台。

該列表可能是不完整的,甚至在某些地方是錯誤的。如果有疑問,請查閱 Perl 源發行版中的特定於平台的 README 文件,以及任何其他附帶特定端口的文檔資源。

此外,請注意,即使在類 Unix 的系統中也存在差異。

對於許多函數,您還可以查詢默認從 Config 模塊導出的 %Config。例如,要檢查平台是否具有 lstat 調用,請檢查 $Config{d_lstat}。有關可用變量的詳細描述,請參見 Config

按字母順序列出的 Perl 函數

-X

(Win32) -w 僅檢查只讀文件屬性(FILE_ATTRIBUTE_READONLY),該屬性決定目錄是否可被刪除,而不是是否可寫入。目錄始終具有讀寫訪問權限,除非由自由訪問控制列表(DACLs)拒絕。

(VMS) -r-w-x-o 告訴文件是否可訪問,這可能不反映基於 UIC 的文件保護。

(RISC OS) -s透過檔案名稱在開啟的檔案上返回磁碟上保留的空間,而不是當前範圍。在開啟的檔案處理程式上使用-s將返回目前大小。

(Win32、VMS、RISC OS) -R-W-X-O無法區分於-r-w-x-o

(Win32、VMS、RISC OS) -g-k-l-u-A並不特別有意義。

(Win32) -l對於符號連結和目錄連結都返回true。

(VMS、RISC OS) -p並不特別有意義。

(VMS) 若傳遞了沒有明確目錄的設備規範,則-d返回true。

(Win32) -x(或-X)用於確定檔案是否以可執行的後綴結尾。-S無意義。

(RISC OS) -x(或-X)用於確定檔案是否具有可執行檔案類型。

alarm

(Win32) 使用計時器進行模擬,每當Perl希望調度"安全信號"時,都必須顯式地輪詢,因此無法中斷阻塞系統呼叫。

atan2

(Tru64、HP-UX 10.20) 由於各種CPU、數學庫、編譯器和標準存在問題,atan2的結果可能會因上述任意組合而有所不同。Perl嘗試符合從atan2返回的結果的Open Group/IEEE標準,但如果系統上運行Perl的系統不允許,則無法強制執行。

有關atan2的當前標準版本可在http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html上找到。

binmode

(RISC OS) 無意義。

(VMS) 重新打開檔案並還原指標;如果函數失敗,則底層檔案處理程式可能會被關閉,或者指標可能處於不同的位置。

(Win32) 在調用之後,tell返回的值可能會受到影響,並且檔案處理程式可能會被刷新。

chdir

(Win32) 系統報告的當前目錄可能包含指定給chdir()的任何符號連結。

chmod

(Win32) 只能用於更改"所有者"的讀寫訪問權限;"群組"和"其他"位無意義。

(RISC OS) 僅適用於更改「所有者」和「其他」的讀寫權限。

(VOS) 存取權限被映射到 VOS 存取控制清單的更改上。

(Cygwin) 實際權限設置取決於系統環境設置中 CYGWIN 變數的值。

(Android) 在某些位置(通常是 /sdcard)上設置執行位會返回 true,但實際上不會設置該位。

(VMS) 模式參數為零時會將權限設置為使用者的默認權限遮罩,而不是禁用所有權限。

chown

(Plan 9, RISC OS) 未實現。

(Win32) 什麼也不做,但不會失敗。

(VOS) 有點奇怪,因為 VOS 的所有權觀念有點奇怪。

chroot

(Win32, VMS, Plan 9, RISC OS, VOS) 未實現。

crypt

(Win32) 如果構建 Perl 時未提供庫或源,則可能無法使用。

(Android) 未實現。

dbmclose

(VMS, Plan 9, VOS) 未實現。

dbmopen

(VMS, Plan 9, VOS) 未實現。

dump

(RISC OS) 無用。

(Cygwin, Win32) 不支援。

(VMS) 調用 VMS 調試器。

exec

(Win32) exec LIST 沒有使用間接對象語法(exec PROGRAM LIST)時,可能會在第一個 spawn() 失敗後嘗試使用 shell。

請注意,exec() 的列表形式是模擬的,因為 Win32 API 的 CreateProcess() 接受一個簡單的字符串而不是一個命令行參數陣列。這可能對您的代碼有安全影響。

(SunOS, Solaris, HP-UX) 在某些平台上不會自動刷新輸出處理程序。

exit

(VMS) 模擬 Unix exit(將 exit 1 視為錯誤)將 1 對應至 SS$_ABORT44)。此行為可透過 pragma use vmsish 'exit' 覆蓋。與 CRTL 的 exit() 函式一樣,exit 0 也對應至退出狀態 SS$_NORMAL1);此對應無法被覆蓋。對 exit 的任何其他參數都直接作為 Perl 的退出狀態。在 VMS 上,除非啟用未來的 POSIX_EXIT 模式,退出代碼應始終是有效的 VMS 退出代碼,而非通用數字。當啟用 POSIX_EXIT 模式時,通用數字將以與 C 函式庫 _POSIX_EXIT 宏兼容的方式編碼,以便其他程序(特別是用 C 編寫的程序,如 GNV 套件)能夠解碼。

(Solaris) exit 重置文件指針,在從 fork 創建的子進程(在 BEGIN 中調用)中調用時會出現問題。一個解決方法是使用 POSIX::_exit

exit unless $Config{archname} =~ /\bsolaris\b/;
require POSIX;
POSIX::_exit(0);
fcntl

(Win32) 未實現。

(VMS) 根據 VMS 的版本可用的一些函數。

flock

(VMS、RISC OS、VOS) 未實現。

fork

(AmigaOS、RISC OS、VMS) 未實現。

(Win32) 使用多個解釋器進行模擬。請參閱 perlfork

(SunOS, Solaris, HP-UX) 在某些平台上不會自動刷新輸出處理程序。

getlogin

(RISC OS) 未實現。

getpgrp

(Win32、VMS、RISC OS) 未實現。

getppid

(Win32、RISC OS) 未實現。

getpriority

(Win32、VMS、RISC OS、VOS) 未實現。

getpwnam

(Win32) 未實現。

(RISC OS) 無用。

getgrnam

(Win32、VMS、RISC OS) 未實現。

getnetbyname

(Android、Win32、Plan 9) 未實現。

getpwuid

(Win32) 未實現。

(RISC OS) 無用。

getgrgid

(Win32、VMS、RISC OS) 未實現。

getnetbyaddr

(Android、Win32、Plan 9) 未實現。

getprotobynumber

(Android) 未實現。

getpwent

(Android, Win32) 尚未實作。

getgrent

(Android, Win32, VMS) 尚未實作。

gethostbyname

(Irix 5) gethostbyname('localhost') 在所有地方都不適用:您可能需要使用 gethostbyname('127.0.0.1')

gethostent

(Win32) 未實現。

getnetent

(Android、Win32、Plan 9) 未實現。

getprotoent

(Android、Win32、Plan 9) 未實現。

getservent

(Win32, Plan 9) 尚未實作。

seekdir

(Android) 未實現。

sethostent

(Android, Win32, Plan 9, RISC OS) 尚未實作。

setnetent

(Win32, Plan 9, RISC OS) 尚未實作。

setprotoent

(Android, Win32, Plan 9, RISC OS) 尚未實作。

setservent

(Plan 9, Win32, RISC OS) 尚未實作。

endpwent

(Win32) 未實現。

(Android) 未實作或不執行任何操作。

endgrent

(Android, RISC OS, VMS, Win32) 尚未實作。

endhostent

(Android, Win32) 尚未實作。

endnetent

(Android、Win32、Plan 9) 未實現。

endprotoent

(Android、Win32、Plan 9) 未實現。

endservent

(Plan 9, Win32) 尚未實作。

getsockopt

(Plan 9) 尚未實作。

glob

此運算子在大多數平台上透過 File::Glob 擴展實作。有關可攜性資訊,請參閱 File::Glob

gmtime

理論上,gmtime 的可靠性範圍為 -2**63 到 2**63-1。但是,由於實作中的解決方法使用浮點數,隨著時間變大,它將變得不精確。這是一個錯誤,將來將予以修復。

(VOS) 時間值是 32 位元的量。

ioctl

(VMS) 尚未實作。

(Win32) 僅適用於套接字處理,其功能與 Winsock API 中的 ioctlsocket() 呼叫相同。

(RISC OS) 僅適用於套接字處理。

kill

(RISC OS) 尚未實作,因此對於檢查污點並不有用。

(Win32) kill 在 Unix 平台上的作用不同於其在 Unix 平台上的功能。在 Win32 上,kill($sig, $pid) 會終止由 $pid 標識的進程,並使其立即以退出狀態 $sig 結束。與 Unix 一樣,如果 $sig 為 0,並且指定的進程存在,則返回 true 而不實際終止該進程。

(Win32) kill(-9, $pid) 將終止指定的進程 $pid 以及它擁有的所有子進程。這與 Unix 語義不同,Unix 中該信號將傳遞給與由 $pid 指定的進程相同的進程組中的所有進程。

(VMS) 尚不支援表示系統上所有進程的 pid -1。

(RISC OS, VOS) 未實現。

(AmigaOS) 連結計數未更新,因為硬連結並不像硬連結那樣堅固(它們在硬連結和符號連結之間有點像中途)。

(Win32) Win32 上僅在 NTFS 下實現了硬連結。它們在 Windows 2000 及更高版本上被原生支持。在 Windows NT 上,它們是使用 Windows POSIX 子系統支持實現的,並且 Perl 進程將需要管理員或備份操作員特權才能創建硬連結。

(VMS) 在 64 位 OpenVMS 8.2 及更高版本上可用。

本地時間

localtime 的範圍與 "gmtime" 相同,但由於時區規則會改變,其對歷史和未來時間的準確性可能會降低,但通常不超過一小時。

lstat

(RISC OS) 未實現。

(Win32) 將目錄連接視為符號連結。

msgctl
msgget
msgsnd
msgrcv

(Android, Win32, VMS, Plan 9, RISC OS, VOS) 未實現。

打開

(RISC OS) 不支持打開模式 |--|

(SunOS, Solaris, HP-UX) 在某些平台上打開進程不會自動刷新輸出處理程序。

(Win32) 支持模式 |--|,但是以列表形式模擬,因為 Win32 API CreateProcess() 接受一個簡單的字符串而不是一個參數數組。這可能會對您的代碼造成安全影響。

(VMS, RISC OS) 未實現。

(Win32) 在目錄連接上調用 readlink() 會返回對象名稱,而不是一個簡單的路徑。

rename

(Win32) 無法在不同邏輯卷之間移動目錄。

rewinddir

(Win32) 不會導致 readdir 重新讀取目錄流。在 rewinddir 呼叫之前已經讀取的條目將從緩存緩衝區再次返回。

select

(Win32, VMS) 僅在套接字上實現。

(RISC OS) 僅在套接字上可靠。

請注意 select FILEHANDLE 形式通常是可移植的。

semctl
semget
semop

(Android, Win32, VMS, RISC OS) 未實現。

setgrent

(Android, VMS, Win32, RISC OS) 未實現。

setpgrp

(Win32、VMS、RISC OS、VOS) 未實現。

setpriority

(Win32、VMS、RISC OS、VOS) 未實現。

setpwent

(Android, Win32, RISC OS) 未實現。

setsockopt

(Plan 9) 尚未實作。

shmctl
shmget
shmread
shmwrite

(Android, Win32, VMS, RISC OS) 未實現。

sleep

(Win32) 通過同步功能模擬,以便可以被 alarm 中斷,並且最多限制為 4294967 秒,大約 49 天。

socketpair

(RISC OS) 未實現。

(VMS) 在 64 位 OpenVMS 8.2 及更高版本上可用。

stat

不具有 rdev, blksize, 或 blocks 的平台將返回這些為 '',因此對這些字段的數值比較或操作可能導致 'not numeric' 警告。

(Mac OS X) 在 UFS 上不支持 ctime

(Win32) ctime 是創建時間而不是inode更改時間。

(VMS) devino 不一定可靠。

(RISC OS) mtime, atimectime 都返回最後修改時間。 devino 不一定可靠。

(OS/2) dev, rdev, blksize, 和 blocks 不可用。 ino 沒有意義,並且在相同文件的 stat 調用之間將不同。

(Cygwin)某些版本的Cygwin在执行stat("foo")时,如果找不到该文件,可能会尝试执行stat("foo.exe")

(RISC OS) 未實現。

(Win32)需要提升的權限或開發人員模式以及足夠新版本的Windows 10。您可以使用Win32::IsSymlinkCreationAllowed() 函式來檢查當前進程是否具有所需的特權。

由於Windows在創建鏈接時需要知道目標是目錄還是其他,因此當目標存在且是目錄時,Perl只會創建目錄鏈接。

Windows不會將斜杠視為符號鏈接中的路徑分隔符號。因此,在Windows上,symlink() 中OLDFILE 參數中的任何/都會轉換為\。這反映在readlink()返回的結果中,結果中的\不會被轉換回/

(VMS)在64位VMS 8.3上實現。如果意圖解析為有效路徑,VMS要求符號鏈接使用Unix語法。

系統調用

(Win32、VMS、RISC OS、VOS) 未實現。

sysopen

Mac OS,OS/390)傳統的012模式在某些系統上使用不同的數值實現。由Fcntl導出的標誌(O_RDONLYO_WRONLYO_RDWR)應該在所有地方都有效。

系統

(Win32)作為優化,可能不會調用在$ENV{PERL5SHELL}中指定的命令shell。 system(1, @args)會生成一個外部進程並立即返回其進程標識符,而不等待其終止。隨後可以在waitwaitpid中使用返回值。無法spawn()子進程的失敗將通過將$?設置為255 << 8來指示。 $?以與Unix兼容的方式設置(即通過$? >> 8獲取子進程的退出狀態,如文檔中所述)。

請注意,系統()的列表形式是模擬的,因為Win32 API CreateProcess()接受一個簡單的字符串而不是命令行參數數組。這可能對您的代碼有安全影響。

(RISC OS) 沒有外殼來處理元字符,本地標準是將以 "\n" "\r" 或 "\0" 結束的命令行傳遞給生成的程式。重定向例如 > foo 是由生成的程式的運行時庫(如果有的話)執行。 system LIST 會調用 Unix 模擬庫的 exec 模擬,該模擬試圖提供父代中強制使用的 stdin、stdout、stderr 的模擬,前提是子程式使用兼容版本的模擬庫。 system SCALAR 將直接調用本地命令行,並且不會發生對子 Unix 程式的任何模擬。里程 可能會 變化。

(Win32) 如果未使用間接對象語法(system PROGRAM LIST),system LIST 可能會在第一個 spawn() 失敗後嘗試回退到使用外殼。

(SunOS, Solaris, HP-UX) 在某些平台上不會自動刷新輸出處理程序。

(VMS) 與 Win32 一樣,system(1, @args) 會生成外部進程並立即返回其進程識別符,而不等待進程終止。在這種情況下,返回值可以稍後在 waitwaitpid 中使用。否則,返回值類似 POSIX(向上移動 8 位),僅允許從本地 32 位條件代碼的嚴重位衍生的虛構值(除非通過 use vmsish 'status' 覆蓋)。如果本地條件代碼是編碼有 POSIX 值的條件代碼,則將解碼 POSIX 值以提取預期的退出值。有關更多詳細信息,請參閱 perlvms 中的 "$?"

telldir

(Android) 未實現。

times

(Win32) "累計" 時間將是錯誤的。除了 Windows NT 或 Windows 2000 之外,"system" 時間將是錯誤的,而 "user" 時間實際上是由 C 執行時庫中的 clock() 函數返回的時間。

(RISC OS) 無用。

truncate

(舊版本的 VMS) 未實現。

(VOS) 只能截斷到相同或更短的長度。

(Win32) 如果提供了 FILEHANDLE,它必須是可寫的並以附加模式打開(即,使用 open(my $fh, '>>', 'filename')sysopen(my $fh, ..., O_APPEND|O_RDWR))。如果提供了文件名,則不應在其他地方保持打開。

umask

當不可用時返回undef

(AmigaOS) umask 正常運作,但正確權限僅在檔案最終關閉時設定。

utime

(VMS, RISC OS) 僅更新修改時間。

(Win32) 可能不會按預期運作。行為取決於C執行時庫對utime()的實作,以及正在使用的檔案系統。FAT檔案系統通常不支援「存取時間」欄位,並可能將時間戳記限制為兩秒的粒度。

等待
等待進程

(Win32) 只能應用於使用system(1, ...)生成的進程句柄,或使用fork創建的偽進程。

(RISC OS) 無用。

支援的平台

以下平台已知可以從可在http://www.cpan.org/src上獲得的標準源代碼發布中構建 Perl 5.12(截至2010年4月,其發布日期)

Linux (x86, ARM, IA64)
HP-UX
AIX
Win32
Windows 2000
Windows XP
Windows Server 2003
Windows Vista
Windows Server 2008
Windows 7
Cygwin

已知一些測試會失敗

Solaris (x86, SPARC)
OpenVMS
Alpha (7.2 及更高版本)
I64 (8.2 及更高版本)
NetBSD
FreeBSD
Debian GNU/kFreeBSD
Haiku
Irix(6.5. 還有其他?)
OpenBSD
Dragonfly BSD
Midnight BSD
QNX Neutrino RTOS(6.5.0)
MirOS BSD
Stratus OpenVOS(17.0 或更新版本)

注意事項

可能已經或尚未解決的 time_t 問題
Stratus VOS / OpenVOS
AIX
Android
FreeMINT

Perl 現在可以在 FreeMiNT/Atari 上建置。它無法通過一些測試,需要進行一些調查。

FreeMiNT 版本使用 GNU dld 來提供可加載模組的功能。因此,在建置 perl 時,請確保已安裝了該庫。

已停止支援的平台

(Perl 5.37.1)

以下平台曾受前一版本的 Perl 支援,但已於 Perl 5.37.1 的源代碼中正式移除

Ultrix

(Perl 5.36)

以下平台曾受前一版本的 Perl 支援,但已於 Perl 5.36 的源代碼中正式移除

NetWare
DOS/DJGPP
AT&T UWIN

(Perl 5.20)

以下平台曾受前一版本的 Perl 支援,但已於 Perl 5.20 的源代碼中正式移除

AT&T 3b1

(Perl 5.14)

以下平台曾受到 5.10 版本的支援。它們可能仍然可以在 5.12 中運行,但在 5.14 中已移除了支援代碼

Windows 95
Windows 98
Windows ME
Windows NT4

(Perl 5.12)

以下平台曾經受到先前版本的 Perl 支援,但自 5.12 版本起已從 Perl 的原始碼正式移除

Atari MiNT
Apollo Domain/OS
Apple Mac OS 8/9
Tenon Machten

支援的平台 (Perl 5.8)

截至 2002 年 7 月 (Perl 5.8.0 發行版本),以下平台能夠從 http://www.cpan.org/src/ 取得標準源代碼分發版並編譯 Perl。

AIX
BeOS
BSD/OS          (BSDi)
Cygwin
DG/UX
DOS DJGPP       1)
DYNIX/ptx
EPOC R5
FreeBSD
HI-UXMPP        (Hitachi) (5.8.0 worked but we didn't know it)
HP-UX
IRIX
Linux
Mac OS Classic
Mac OS X        (Darwin)
MPE/iX
NetBSD
NetWare
NonStop-UX
ReliantUNIX     (formerly SINIX)
OpenBSD
OpenVMS         (formerly VMS)
Open UNIX       (Unixware) (since Perl 5.8.1/5.9.0)
OS/2
OS/400          (using the PASE) (since Perl 5.8.1/5.9.0)
POSIX-BC        (formerly BS2000)
QNX
Solaris
SunOS 4
SUPER-UX        (NEC)
Tru64 UNIX      (formerly DEC OSF/1, Digital UNIX)
UNICOS
UNICOS/mk
UTS
VOS / OpenVOS
Win95/98/ME/2K/XP 2)
WinCE
z/OS            (formerly OS/390)
VM/ESA

1) in DOS mode either the DOS or OS/2 ports can be used
2) compilers: Borland, MinGW (GCC), VC6

以下平台與之前版本 (5.6 和 5.7) 兼容,但我們在 5.8.0 版本發佈之前未能及時修復或測試這些問題。很可能其中許多平台與 5.8.0 版本能夠正常運作。

BSD/OS
DomainOS
Hurd
LynxOS
MachTen
PowerMAX
SCO SV
SVR4
Unixware
Windows 3.1

已知 5.8.0 版本存在問題 (但 5.6.1 和 5.7.2 版本可用)

AmigaOS 3

以下平台過去已知能夠從源代碼構建 Perl (5.005_03 和更早版本),但我們無法驗證它們在當前版本的狀態,可能因為硬體/軟體平台較為罕見,或者因為我們沒有在這些平台上的積極支持者——或兩者兼而有之。儘管如此,它們曾經可用,所以您可以嘗試編譯它們,並通知 https://github.com/Perl/perl5/issues 知悉任何問題。

3b1
A/UX
ConvexOS
CX/UX
DC/OSx
DDE SMES
DOS EMX
Dynix
EP/IX
ESIX
FPS
GENIX
Greenhills
ISC
MachTen 68k
MPC
NEWS-OS
NextSTEP
OpenSTEP
Opus
Plan 9
RISC/os
SCO ODT/OSR
Stellar
SVR2
TI1500
TitanOS
Unisys Dynix

以下平台有其自己的源代碼分發版和二進制文件,可通過 http://www.cpan.org/ports/ 取得。

                        Perl release

OS/400 (ILE)            5.005_02
Tandem Guardian         5.004

以下平台僅有二進制文件,可通過 http://www.cpan.org/ports/index.html 取得

                        Perl release

Acorn RISCOS            5.005_02
AOS                     5.002
LynxOS                  5.004_02

儘管我們建議您始終從源代碼構建自己的 Perl,以實現最大程度的可配置性和安全性,但如果您趕時間,可以查看 http://www.cpan.org/ports/index.html 以獲取二進制發行版。

參見

perlaix, perlamiga, perlbs2000, perlcygwin, perlebcdic, perlfreebsd, perlhurd, perlhpux, perlirix, perlmacosx, perlos2, perlos390, perlos400, perlplan9, perlqnx, perlsolaris, perltru64, perlunicode, perlvms, perlvos, perlwin32, 和 Win32.

作者 / 貢獻者

Abigail <abigail@abigail.be>, Charles Bailey <bailey@newman.upenn.edu>, Graham Barr <gbarr@pobox.com>, Tom Christiansen <tchrist@perl.com>, Nicholas Clark <nick@ccl4.org>, Thomas Dorner <Thomas.Dorner@start.de>, Andy Dougherty <doughera@lafayette.edu>, Dominic Dunlop <domo@computer.org>, Neale Ferguson <neale@vma.tabnsw.com.au>, David J. Fiander <davidf@mks.com>, Paul Green <Paul.Green@stratus.com>, M.J.T. Guy <mjtg@cam.ac.uk>, Jarkko Hietaniemi <jhi@iki.fi>, Luther Huffman <lutherh@stratcom.com>, Nick Ing-Simmons <nick@ing-simmons.net>, Andreas J. König <a.koenig@mind.de>, Markus Laker <mlaker@contax.co.uk>, Andrew M. Langmead <aml@world.std.com>, Lukas Mai <l.mai@web.de>, Larry Moore <ljmoore@freespace.net>, Paul Moore <Paul.Moore@uk.origin-it.com>, Chris Nandor <pudge@pobox.com>, Matthias Neeracher <neeracher@mac.com>, Philip Newton <pne@cpan.org>, Gary Ng <71564.1743@CompuServe.COM>, Tom Phoenix <rootbeer@teleport.com>, André Pirard <A.Pirard@ulg.ac.be>, Peter Prymmer <pvhp@forte.com>, Hugo van der Sanden <hv@crypt0.demon.co.uk>, Gurusamy Sarathy <gsar@activestate.com>, Paul J. Schinder <schinder@pobox.com>, Michael G Schwern <schwern@pobox.com>, Dan Sugalski <dan@sidhe.org>, Nathan Torkington <gnat@frii.com>, John Malmberg <wb8tyw@qsl.net>