perl5004delta - perl5.004 的新功能
本文件描述了 5.003 版本(在《Perl 程式設計》第二版--駱駝書中有記載)與本版本之間的差異。
Perl5.004 在 Unix、Plan 9、LynxOS、VMS、OS/2、QNX、AmigaOS 和 Windows NT 上可以直接構建。Perl 也運行在 Windows 95 上,但由於缺乏合理的命令解析器,無法在那裡構建。
最重要的是,許多錯誤已修復,包括幾個安全問題。詳情請參閱發行版中的 Changes 檔案。
%ENV = ()
和 %ENV = @list
現在可以正常工作(在 VMS 上會生成致命錯誤除外)。
錯誤 "Can't locate Foo.pm in @INC" 現在會列出 @INC 的內容,以便更容易進行調試。
有一個新的 Configure 問題,詢問您是否希望保持與 Perl 5.003 的二進制兼容性。如果選擇了二進制兼容性,則無需重新編譯您的擴展,但如果將 Perl 嵌入另一個應用程序中,可能會出現符號衝突,就像在 5.003 發行版中一樣。默認情況下,保留二進制兼容性會增加符號表污染的風險。
現在可以將 Perl 選項放入 $PERL5OPT 環境變量中。除非 Perl 正在執行 taint 檢查,否則它將解釋此變量,就像其內容出現在腳本開頭的 "#!perl" 行中一樣,只是中間的破折號是可選的。PERL5OPT 只能用於設置以下開關:-[DIMUdmw]。
在腳本的 #!
行中不再允許使用 -M
和 -m
選項。如果腳本需要一個模組,應該使用 use
pragma 來調用它。
#!
行中也禁止使用 -T 選項,除非它存在於 Perl 命令行中。由於 #!
的工作方式,這通常意味著 -T 必須在第一個參數中。因此
#!/usr/bin/perl -T -w
對於作為 scriptname
調用的可執行腳本可能會工作,而
#!/usr/bin/perl -w -T
在相同條件下可能會失敗。(非Unix系統可能不遵循此規則。)但是 perl scriptname
是保證會失敗的,因為在發現 -T 在 #!
行之前找不到它在命令行上。
如果您從您的 Perl 5.003 腳本中刪除了 -w 選項,因為它使 Perl 太冗長,我們建議您在升級到 Perl 5.004 時嘗試將其放回。每個新的 perl 版本都傾向於刪除一些不需要的警告,同時添加可能會捕獲到您腳本中的錯誤的新警告。
AUTOLOAD
在 Perl 5.004 之前,即使要自動加載的函數被調用為普通函數(例如 Foo::bar()
),而不是作為方法(例如 Foo->bar()
或 $obj->bar()
),AUTOLOAD
函數也會被視為方法(使用 @ISA
階層)。
Perl 5.005 將僅為方法的 AUTOLOAD
使用方法查找。但是,現有的代碼庫可能使用舊的行為。因此,作為一個過渡步驟,Perl 5.004 在非方法使用繼承的 AUTOLOAD
時發出可選警告。
簡單的規則是:自動加載非方法時,繼承將不起作用。舊代碼的簡單修復方法是:在任何以前依賴於從名為 BaseClass
的基類繼承非方法的模塊中,在啟動期間執行 *AUTOLOAD = \&BaseClass::AUTOLOAD
。
在 5.003 中,使用 %OVERLOAD 定義重載已被棄用。現在使用 overload pragma 來定義重載。%OVERLOAD 仍然在內部使用,但不應被 Perl 腳本使用。有關詳細信息,請參見 overload。
在Perl 5.004中,假如不存在的陣列和雜湊元素被當作子程式參數,只有當它們實際上被分配(通過@_
)時才會被建立。
Perl的較早版本在處理此類引數時有所不同。Perl版本5.002和5.003總是會建立它們。Perl版本5.000和5.001只有在它們不是第一個參數時才會建立它們(這幾乎可以肯定是一個錯誤)。Perl的更早版本從不會建立它們。
例如,給定這段程式碼
undef @a; undef %a;
sub show { print $_[0] };
sub change { $_[0]++ };
show($a[2]);
change($a{b});
在Perl 5.004中執行此程式碼後,$a{b}存在,但$a[2]不存在。在Perl 5.002和5.003中,$a{b}和$a[2]都會存在(但$a[2]的值將是未定義的)。
$)
可變更群組向量特殊變數$)
一直(至少在Perl 5中是如此)反映了當前的有效群組,以及由getgroups()
C函數返回的群組列表(如果有的話)。然而,直到這個版本,尚未有辦法從Perl調用setgroups()
C函數。
在Perl 5.004中,將值指派給$)
與檢查它完全對稱:其字串值中的第一個數字被用作有效的gid;如果第一個數字後還有其他數字,則它們將傳遞給setgroups()
C函數(如果有的話)。
在Perl 5.004之前的版本中,任何後面跟著"$"和數字的類型標記都被誤解。例如,"$$0"被錯誤地解釋為"${$}0"而不是"${$0}"。這個錯誤在Perl 5.004中(大部分)得到了修復。
然而,Perl 5.004的開發者無法完全修復這個錯誤,因為至少有兩個廣泛使用的模組依賴於在字串中"$<digit>"的舊含義。因此,Perl 5.004在字串內部仍然像舊的(錯誤的)方式解釋"$<digit>",但它會生成此警告訊息。在Perl 5.005中,這種特殊處理將停止。
在Perl 5.004之前的版本中,並不總是正確地將與正則表達式相關的特殊變數本地化。Perl 5.004確實將它們本地化,正如文檔一直所說的那樣。這可能會導致$1、$2等在現有程序中不再被設置。
Perl 5.0的文檔一直指出,當已打開的文件處理器重新打開時,$.
並不會重置。由於一個錯誤,perl版本5.000到5.003在這種情況下確實重置了$.
;Perl 5.004則沒有這樣做。
wantarray
可能返回undefwantarray
運算符如果期望子程式返回一個列表則返回true,否則返回false。在Perl 5.004中,如果子程式的返回值根本不會被使用,w
eval EXPR
在標量內文中決定 EXPR 的值。Perl(版本 5)以前會不一致地確定 EXPR 的值,有時會錯誤地使用周圍的內文來確定。現在,在被 eval 解析之前,EXPR 的值(在標量內文中)始終會被確定。一旦被解析,它就像以前一樣被執行,提供了周圍 eval 所提供的內文。這個改變使得行為與 Perl4 兼容,並修正了由於不一致行為而導致的錯誤。這個程式
@a = qw(time now is time);
print eval @a;
print '|', scalar eval @a;
以前會打印類似 "timenowis881399109|4" 的東西,但現在(以及在 perl4 中)打印 "4|4"。
在以前的版本中,當開啟塗污檢查時,可能會未能檢測到一些不安全的條件。(塗污檢查在 setuid 或 setgid 腳本中使用,或者在明確使用 -T
呼叫選項時使用。)儘管可能性很小,但這可能會導致以前有效的腳本現在失敗,這應該被視為一種幸運,因為這表明了一個潛在的嚴重安全漏洞被修補了。
當塗污檢查時的新限制包括
這些運算子可能會生成 C shell(csh),這無法被安全地使用。當 globbing 不再使用外部程式時,這個限制將在 Perl 的將來版本中被取消。
這些環境變數可能會以一種破壞性的方式改變產生的程式(尤其是殼程式)的行為,從而破壞安全性。因此,現在將它們視為危險,就像 $IFS 和 $PATH 一樣。
一些 termcap 庫對 $TERM 執行不安全的操作。然而,將所有 $TERM 值都視為不安全是不必要的,因為只有殼元字符才會在 $TERM 中引起麻煩。因此,如果一個污染的 $TERM 只包含字母數字、下劃線、破折號和冒號,則被視為安全,如果它包含其他字符(包括空格),則被視為不安全。
新的 Opcode 模組支援建立、操作和應用操作碼遮罩。修訂版的 Safe 模組具有新的 API,並使用新的 Opcode 模組實現。請參閱新的 Opcode 和 Safe 文件。
在舊版本的 Perl 中,在單個進程內無法創建多個 Perl 解釋器實例而不會像篩子一樣洩漏和/或崩潰。導致此行為的錯誤都已經修正。然而,在將 Perl 嵌入 C 程序時,您仍然必須小心。請參閱更新的 perlembed 手冊頁,了解如何管理您的解釋器的提示。
文件處理程序現在在內部以 IO::Handle 類型存儲。FileHandle 模組仍然支持向後兼容性,但現在僅僅是 IO::* 模組的前端,具體而言是 IO::Handle、IO::Seekable 和 IO::File。我們建議,但不要求,您在新代碼中使用 IO::* 模組。
與此更改相一致,*GLOB{FILEHANDLE}
現在只是 *GLOB{IO}
的向後兼容同義詞。
現在可以使用 AT&T 的 sfio IO 套件而不是 stdio 來構建 Perl。有關更多詳細信息,請參閱 perlapio,以及如何使用它的 INSTALL 文件。
現在可以在子例程引用後緊接著箭頭和(可能為空的)參數列表。此語法表示使用給定的參數(如果有的話)調用引用的子例程。
此新語法遵循 $hashref->{FOO}
和 $aryref->[$foo]
的模式:現在您可以將 &$subref($foo)
寫成 $subref->($foo)
。所有這些箭頭術語都可以連鎖使用;因此,&{$table->{FOO}}($bar)
現在可以寫成 $table->{FOO}->($bar)
。
編譯時的當前套件名稱,如果沒有當前套件(由於 package;
指令而導致),則為未定義值。與 __FILE__
和 __LINE__
一樣,__PACKAGE__
不會在字符串中進行插值。
某些平台上的擴展錯誤消息。(如果使用 use English
則稱為 $EXTENDED_OS_ERROR)。
use strict
啟用的當前語法檢查集。有關詳細信息,請參閱 strict
的文檔。實際上並不是新的,但是新近記錄下來。因為它是由 Perl 核心組件內部使用的,所以沒有此變數的 use English
長名稱。
默認情況下,耗盡內存無法捕獲。但是,如果編譯了 Perl 以進行此操作,Perl 可能會在此消息與 die() 之後使用 $^M
的內容作為緊急池。假設您的 Perl 是使用 -DPERL_EMERGENCY_SBRK 編譯並使用 Perl 的 malloc。然後
$^M = 'a' x (1<<16);
將為緊急情況下分配一個 64K 緩衝區。有關如何啟用此選項的信息,請參閱 INSTALL 文件。為了阻止此高級功能的隨意使用,此變數沒有 use English
的長名稱。
現在這樣操作。(例如:delete @ENV{'PATH', 'MANPATH'}
)
現在在更多平台上支援,模擬時更喜歡使用 fcntl 而不是 lockf,並且在(解)鎖定之前始終刷新。
Perl 現在自己實現這些函數;它不再使用 C 函數 sprintf(),除了浮點數之外,即使是已知的標誌也只允許。因此,現在可以知道哪些轉換和標誌將起作用,以及它們將做什麼。
在Perl的sprintf()中新增的轉換是
%i a synonym for %d
%p a pointer (the address of the Perl value, in hexadecimal)
%n special: *stores* the number of characters output so far
into the next variable in the parameter list
放在%
和轉換之間的新標記是
# prefix octal with "0", hex with "0x"
h interpret integer as C type "short" or "unsigned short"
V interpret integer as Perl's standard integer type
此外,當標記中應該出現一個數字時,可以改用星號("*")代替,此時Perl將使用參數列表中的下一個項目作為給定的數字(即作為字段寬度或精度)。如果通過"*"獲取的字段寬度為負數,則與'-'標誌具有相同的效果:左對齊。
有關轉換和標記的完整列表,請參見perlfunc中的"sprintf"。
作為左值,keys
允許您增加分配給給定哈希的哈希桶的數量。如果您知道哈希將變大,這可以為您帶來一定程度的效率。 (這與通過將較大的數字分配給$#array來預先擴展數組類似。)如果您說
keys %hash = 200;
那麼%hash
將至少有200個桶為其分配。即使您執行%hash = ()
,這些桶也將被保留;如果您希望在%hash
仍在作用域內時釋放存儲,請使用undef %hash
。您不能通過此方式使用keys
來縮小分配給哈希的桶的數量(但是您不必擔心出錯,因為試圖這樣做不會產生任何效果)。
您現在可以在控制結構(如)的控制表達式中使用my()(帶括號或不帶括號都可以)
while (defined(my $line = <>)) {
$line = lc $line;
} continue {
print $line;
}
if ((my $answer = <STDIN>) =~ /^y(es)?$/i) {
user_agrees();
} elsif ($answer =~ /^n(o)?$/i) {
user_disagrees();
} else {
chomp $answer;
die "`$answer' is neither `yes' nor `no'";
}
此外,您可以通過在foreach循環控制變量之前加上單詞"my"來聲明其為詞法變量。例如,在
foreach my $i (1, 2, 3) {
some_function();
}
$i是一個詞法變量,其作用域延伸到循環的結束,但不超出循環範圍。
請注意,仍然無法對全局標點變量(如$_等)使用my()。
新格式'w'表示BER壓縮整數(如ASN.1中定義的)。其格式是一個或多個字節的序列,每個字節提供總值的七位,最高有效位優先。每個字節的第八位設置,除了最後一個字節,其中第八位為清除。
如果給定'p'或'P'的值為undef,則它們現在將生成一個NULL指針。
現在,無論是 pack() 還是 unpack() 在其模板中包含無效類型時都將失敗。(以前會忽略無效類型。)
新的 sysseek() 運算子是 seek() 的變體,它使用 lseek(2) 系統調用設置和獲取文件的系統讀/寫位置。這是在使用 sysread() 或 syswrite() 之前定位的唯一可靠方法。它的返回值是新位置,或失敗時的未定義值。
如果 use
的第一個參數是一個數字,則將其視為版本號而不是模塊名稱。如果 Perl 解釋器的版本小於 VERSION,則會打印一條錯誤消息並立即退出 Perl。因為 use
發生在編譯時,所以此檢查會立即在編譯過程中進行,不像 require VERSION
那樣等到運行時才進行檢查。如果您需要在 use
之前檢查當前的 Perl 版本以使用已從舊版本 Perl 中的不兼容方式更改的庫模塊,則這通常是有用的。(我們盡量不要這樣做得太多。)
如果在 Module 和 LIST 之間存在 VERSION 參數,則 use
將使用給定版本作為參數調用類 Module 中的 VERSION 方法。從 UNIVERSAL 類繼承的默認 VERSION 方法,如果給定的版本大於變量 $Module::VERSION 的值,則會拋出異常。(請注意,VERSION 後面沒有逗號!)
此版本檢查機制類似於當前在 Exporter 模塊中使用的機制,但它更快且可以與不使用 Exporter 的模塊一起使用。這是新代碼的推薦方法。
將函數的原型作為字符串返回(如果函數沒有原型則返回 undef
)。FUNCTION 是您想要檢索其原型的函數的引用或名稱。(這不是新功能;只是以前從未有過文檔。)
預設的種子值已經從time
更改為一組難以預測的系統相關值,這對於大多數日常用途應該是足夠的。
在版本 5.004 之前,如果在呼叫srand
之前呼叫rand
,則在大多數或所有機器上將產生相同的隨機數序列。現在,當 Perl 發現您正在呼叫rand
但尚未呼叫srand
時,它會使用預設種子呼叫srand
。當然,如果您的程式碼可能在 5.004 之前的系統上運行,或者如果您希望使用除了預設值以外的種子,您仍然應該手動呼叫srand
。
在Camel文件中記錄的函數默認為 $_,而實際上也是如此,在perlfunc中記錄了所有這樣的函數。
m//gc
在失敗時不會重置搜索位置在Perl 5.004中,當一個匹配失敗時,m//g
匹配迭代構造始終會重置其目標字符串的搜索位置(通過pos
運算子可見),因此,在失敗後的下一個m//g
匹配將重新從字符串的開頭開始。現在,可以通過添加“c”(表示“繼續”)修飾符來禁用此重置,即m//gc
。這個特性與\G
零寬斷言一起,使得可以將匹配鏈接在一起。請參閱perlop和perlre。
m//x
忽略 ?*+{} 前的空格m//x
構造一直意圖忽略所有未經轉義的空格。然而,在 Perl 5.004 之前,空格會使重複修飾符(如“*”或“?”)生效;例如,/a *b/x
被(錯誤地)解釋為/a\*b/x
。這個錯誤已在 5.004 中修正。
sub{}
閉包現在正常運作在 5.004 版本之前,巢狀匿名函數無法正常工作。現在已經修復了。
就像包含更改的詞彙變數(例如foreach
循環的詞彙索引變數)的匿名函數一樣,格式現在也正常運作。例如,這在以前會默默失敗(只打印零),但現在可以正常運行
my $i;
foreach $i ( 1 .. 10 ) {
write;
}
format =
my i is @#
$i
.
但是,如果foreach在子程序內部,它仍然會失敗(沒有警告)
my $i;
sub foo {
foreach $i ( 1 .. 10 ) {
write;
}
}
foo;
format =
my i is @#
$i
.
UNIVERSAL
套件自動包含以下方法,這些方法被所有其他類別繼承
isa
如果其物件被賦予為CLASS
的子類別,則返回 true
isa
也是可匯出的,並且可以以兩個參數呼叫為子例程。這允許檢查參考指向的內容。範例
use UNIVERSAL qw(isa);
if(isa($ref, 'ARRAY')) {
...
}
can
用於檢查物件是否具有名為 METHOD
的方法,若有則返回對該子例程的引用;若無則返回 undef。
VERSION
返回類別(套件)的版本號碼。如果提供 NEED 參數,則會檢查當前版本(由給定套件中的 $VERSION 變數定義)是否不低於 NEED;若不是則會終止執行。該方法通常作為類別方法呼叫。此方法會被 use
的 VERSION
形式自動呼叫。
use A 1.2 qw(some imported subs);
# implies:
A->VERSION(1.2);
注意: can
直接使用 Perl 內部的方法查找方法,而 isa
使用非常類似的方法和緩存策略。如果 Perl 程式碼動態更改了任何套件中的 @ISA,這可能會導致奇怪的效果。
您可以通過 Perl 或 XS 程式碼將其他方法添加到 UNIVERSAL 類別。您不需要為了使這些方法對您的程式可用而 use UNIVERSAL
。這僅在您希望將 isa
作為當前套件中的普通子例程使用時才是必要的。
參閱 perltie 以獲取其他類型的 tie()。
這是類別的建構子。這意味著預期會返回某種類型的物件。該參考可用於保存一些內部資訊。
sub TIEHANDLE {
print "<shout>\n";
my $i;
return bless \$i, shift;
}
每次將綁定的處理程式列印時,都會觸發此方法。除了自身參考外,它還期望傳遞給列印函式的清單。
sub PRINT {
$r = shift;
$$r++;
return print join( $, => map {uc} @_), $\;
}
每次將帶有 printf()
函式的綁定處理程式列印時,都會觸發此方法。除了自身參考外,它還期望傳遞給 printf 函式的格式和清單。
sub PRINTF {
shift;
my $fmt = shift;
print sprintf($fmt, @_)."\n";
}
當通過 read
或 sysread
函式讀取處理程式時,將調用此方法。
sub READ {
$r = shift;
my($buf,$len,$offset) = @_;
print "READ called, \$buf=$buf, \$len=$len, \$offset=$offset";
}
當從處理程式中讀取時,將調用此方法。當沒有更多資料時,該方法應該返回 undef。
sub READLINE {
$r = shift;
return "PRINT called $$r times\n"
}
當調用getc
函數時,將調用此方法。
sub GETC { print "Don't GETC, Get Perl"; return "a"; }
與其他類型的關聯一樣,當關聯的處理程序即將被銷毀時,將調用此方法。這對於調試和可能的清理很有用。
sub DESTROY {
print "</shout>\n";
}
如果Perl是使用Perl發行版中包含的malloc編譯的(即,如果perl -V:d_mymalloc
是 'define'),則可以通過以下方式在運行時打印內存統計信息運行Perl
env PERL_DEBUG_MSTATS=2 perl your_script_here
值2表示在編譯後和退出時打印統計信息;值1表示統計信息僅在退出時打印。(如果您想在任意時間獲取統計信息,則需要安裝可選模塊Devel::Peek。)
malloc.c識別三個新的編譯標誌。(如果Perl是使用系統malloc()編譯的,則它們不起作用。)
如果定義了此宏,內存耗盡不需要是致命錯誤:可以通過將特殊變量$^M
賦值來分配內存池。參見"$^M"。
Perl內存分配是以接近二次方的大小為桶的。由於這些malloc開銷可能很大,特別是對於大小恰好為二次方的數據。如果定義了PACK_MALLOC
,Perl將使用稍微不同的算法進行小型分配(最多64字節長),這使得對於大小為二次方(並且非常常見)的分配,開銷可以減少到1字節。
預期的內存節省(在alignbytes
中進行8字節對齊)對於典型的Perl用法約為20%。由於額外的malloc開銷,預期的減速率是百分之幾(難以測量,因為已節省的內存對速度的影響)。
與PACK_MALLOC
類似,此宏改善了接近二次方大小的數據的分配;但這適用於大型分配(默認從16K開始)。這種分配對於大型哈希和特殊用途腳本特別常見,尤其是圖像處理。
在最近的系統上,Perl 需要從系統獲取 2M 的空間來分配 1M 的內存將不會影響執行速度,因為這樣一個塊的尾部不會被使用(因此不需要真正的內存)。然而,這可能導致提前的內存不足錯誤。因此,如果您將使用非常大的區塊,其大小接近於二的冪次方,則定義此宏是明智的。
預期的內存節省為 0-100%(對於那些在這樣的 2**n 塊中需要最多內存的應用程序為 100%);預期的減速可以忽略不計。
現在,具有空原型且僅返回固定值的函數被內聯化(例如 sub PI () { 3.14159 }
)。
每個唯一的哈希鍵只分配一次,無論有多少哈希具有該鍵的項目。因此,即使您有 100 個相同哈希的副本,哈希鍵也永遠不需要重新分配。
Perl 5.004 新增支援以下操作系統。
Perl 5.004 現在包括對使用 Microsoft Visual C++ 編譯器(版本 2.0 及以上)或 Borland C++ 編譯器(版本 5.02 及以上)在 Windows NT 下構建“本機” Perl 的支援。生成的 Perl 可以在 Windows 95 下使用(如果安裝在與 Windows NT 中相同的目錄位置)。此端口包括對 Perl 擴展構建工具(如 ExtUtils::MakeMaker 和 h2xs)的支援,因此現在可以輕鬆地在 Windows NT 下構建許多可在 CPAN(Comprehensive Perl Archive Network)上找到的擴展。有關 CPAN 的更多信息,請參閱 http://www.perl.com/,有關如何開始構建此端口的詳細信息,請參閱 Perl 分發中的 README.win32。
還支援在 Cygwin32 環境下構建 Perl。Cygwin32 是一套 GNU 工具,它可以通過提供大部分類 Unix 的編譯和執行界面,在 Windows NT 下編譯和運行許多 Unix 程序。有關此端口的更多信息,以及如何獲取 Cygwin32 工具包的詳細信息,請參閱 Perl 分發中的 README.cygwin32。
請參閱 Perl 分發中的 README.plan9。
請參閱 Perl 分發中的 README.qnx。
請參閱 Perl 分發中的 README.amigaos。
存在六個新的務實模組
推遲 require MODULE
直到有人呼叫指定的子程式之一(該子程式必須由 MODULE 匯出)。這個 pragma 應謹慎使用,僅在必要時使用。
從 dir(或當前目錄)開始尋找類似 MakeMaker 的 'blib' 目錄結構,並向上遞歸至最多五個父目錄。
用於在命令行上使用 -M 選項,以便對未安裝的套件版本測試任意腳本。
提供一個方便的界面來創建編譯時常數,請參見 perlsub 中的 "Constant Functions"。
告訴編譯器啟用(或禁用)內建操作的 POSIX 地區設置。
當 use locale
生效時,當前的 LC_CTYPE 地區用於正則表達式和大小寫轉換;LC_COLLATE 用於字符串排序;LC_NUMERIC 用於 printf 和 sprintf 中的數字格式化(但不用於 print)。在 write 中始終使用 LC_NUMERIC,因為格式的語法作用域問題很棘手。
每個 use locale
或 no locale
影響到該封閉 BLOCK 的末尾,或者如果不在 BLOCK 內,則影響到當前文件的末尾。可以使用 POSIX::setlocale() 切換和查詢地區設置。
請參閱 perllocale 以獲取更多信息。
在編譯 Perl 代碼時禁用不安全的操作碼,或者禁用任何命名的操作碼。
啟用 VMS 特定的語言特性。目前,有三個可用的 VMS 特定功能:'status',使得 $?
和 system
返回真實的 VMS 狀態值,而不是模擬 POSIX;'exit',使得 exit
接受真實的 VMS 狀態值,而不是假設 exit 1
是一個錯誤;'time',使得所有時間都相對於本地時區,在 VMS 的傳統中。
雖然 Perl 5.004 與幾乎所有與 Perl 5.003 相容的模組兼容,但還是有幾個例外。
Module Required Version for Perl 5.004
------ -------------------------------
Filter Filter-1.12
LWP libwww-perl-5.08
Tk Tk400.202 (-w makes noise)
另外,majordomo 郵件列表程式,版本 1.94.1,不與 Perl 5.004 (也不與 perl 4) 兼容,因為它執行了一個無效的正則表達式。這個 bug 在 majordomo 版本 1.94.2 中修復。
installperl 腳本現在將擴展的 Perl 源文件放置在特定架構的庫目錄中,這是擴展的共享庫一直存在的地方。此更改旨在允許管理員將 Perl 5.004 库目錄保持與上一個版本不變,而不會出現擴展的 Perl 源和共享庫之間的二進制不兼容性風險。
全新的模組,按主題排列,而不是嚴格按字母排序
CGI.pm Web server interface ("Common Gateway Interface")
CGI/Apache.pm Support for Apache's Perl module
CGI/Carp.pm Log server errors with helpful context
CGI/Fast.pm Support for FastCGI (persistent server process)
CGI/Push.pm Support for server push
CGI/Switch.pm Simple interface for multiple server types
CPAN Interface to Comprehensive Perl Archive Network
CPAN::FirstTime Utility for creating CPAN configuration file
CPAN::Nox Runs CPAN while avoiding compiled extensions
IO.pm Top-level interface to IO::* classes
IO/File.pm IO::File extension Perl module
IO/Handle.pm IO::Handle extension Perl module
IO/Pipe.pm IO::Pipe extension Perl module
IO/Seekable.pm IO::Seekable extension Perl module
IO/Select.pm IO::Select extension Perl module
IO/Socket.pm IO::Socket extension Perl module
Opcode.pm Disable named opcodes when compiling Perl code
ExtUtils/Embed.pm Utilities for embedding Perl in C programs
ExtUtils/testlib.pm Fixes up @INC to use just-built extension
FindBin.pm Find path of currently executing program
Class/Struct.pm Declare struct-like datatypes as Perl classes
File/stat.pm By-name interface to Perl's builtin stat
Net/hostent.pm By-name interface to Perl's builtin gethost*
Net/netent.pm By-name interface to Perl's builtin getnet*
Net/protoent.pm By-name interface to Perl's builtin getproto*
Net/servent.pm By-name interface to Perl's builtin getserv*
Time/gmtime.pm By-name interface to Perl's builtin gmtime
Time/localtime.pm By-name interface to Perl's builtin localtime
Time/tm.pm Internal object for Time::{gm,local}time
User/grent.pm By-name interface to Perl's builtin getgr*
User/pwent.pm By-name interface to Perl's builtin getpw*
Tie/RefHash.pm Base class for tied hashes with references as keys
UNIVERSAL.pm Base class for *ALL* classes
現在支援現有 Fcntl 模組中的新常數,前提是您的操作系統碰巧支援它們。
F_GETOWN F_SETOWN
O_ASYNC O_DEFER O_DSYNC O_FSYNC O_SYNC
O_EXLOCK O_SHLOCK
這些常數是為 Perl 運算符 sysopen() 和 fcntl() 以及基本的數據庫模組(如 SDBM_File)而設計的。有關這些和其他 Fcntl 常數的確切含義,請參閱您操作系統的 fcntl() 和 open() 的文檔。
此外,Fcntl 模組現在提供這些常數供 Perl 運算符 flock() 使用。
LOCK_SH LOCK_EX LOCK_NB LOCK_UN
這些常數在所有環境中都被定義(因為在沒有 flock() 系統調用的情況下,Perl 會模擬它)。但是,出於歷史原因,除非使用 ":flock" 標籤(例如 use Fcntl ':flock'
)明確要求,否則這些常數不會被導出。
IO 模組提供了一個簡單的機制,可以一次性加載所有 IO 模組。目前包括
IO::Handle
IO::Seekable
IO::File
IO::Pipe
IO::Socket
有關任何這些模組的更多信息,請參閱其相應的文檔。
Math::Complex 模組已完全重寫,現在支援更多操作。這些已被重載
+ - * / ** <=> neg ~ abs sqrt exp log sin cos atan2 "" (stringify)
這些函數現在已被導出
pi i Re Im arg
log10 logn ln cbrt root
tan
csc sec cot
asin acos atan
acsc asec acot
sinh cosh tanh
csch sech coth
asinh acosh atanh
acsch asech acoth
cplx cplxe
這個新模組為那些只需要實數的三角函數的人提供了一個更簡單的接口,用於 Math::Complex 的部分。
DB_File 已經進行了相當多的更改。以下是其中一些亮點
修正了一些錯誤。
根據公眾需求,增加了對標準哈希函數 exists() 的支援。
使其與 Berkeley DB 1.86 兼容。
使負的下標與 RECNO 接口配合工作。
將默認標誌從 O_RDWR 更改為 O_CREAT|O_RDWR,默認模式從 0640 更改為 0666。
如果可用,使 DB_File 自動從 Fcntl 導入 open() 常量(例如 O_RDWR、O_CREAT 等)。
更新了文檔。
請參考 DB_File.pm 中的 HISTORY 部分以獲取完整的更改列表。自 DB_File 1.01 以來添加的所有內容均自 5.003 開始。
重大重寫 - 添加了對udp回聲和真正的icmp ping的支援。
許多返回列表的 Perl 內建函數現在具有面向對象的重寫。
File::stat
Net::hostent
Net::netent
Net::protoent
Net::servent
Time::gmtime
Time::localtime
User::grent
User::pwent
例如,您現在可以這樣說
use File::stat;
use User::pwent;
$his = (stat($filename)->st_uid == pwent($whoever)->pw_uid);
Perl 5.004 中包含的 pod2html 實用程序是全新的。默認情況下,它將轉換後的 HTML 發送到其標準輸出,而不像 Perl 5.003 的 pod2html 那樣將其寫入文件。使用 --outfile=FILENAME 選項將其寫入文件。
void
XSUBs 現在默認不返回任何內容由於以前版本的 Perl 中存在文檔/實現錯誤,因此具有 void
返回類型的 XSUB 實際上一直在返回一個值。通常,該值是 XSUB 的 GV,但有時它是一些已經被釋放或重用的值,這有時會導致程序失敗。
在 Perl 5.004 中,如果將 XSUB 声明為返回 void
,則實際上不返回任何值,即一個空列表(雖然有一個向後兼容的例外情況;請參見下文)。如果您的 XSUB 确實返回一個 SV,則應將其返回類型設置為 SV *
。
為了向後兼容,xsubpp 試圖猜測 void
XSUB 是否真正為 void
,或者它是否希望返回 SV *
。它這樣做是通過檢查 XSUB 的文本來完成的:如果 xsubpp 發現看起來像是對 ST(0)
的賦值,則假定 XSUB 的返回類型實際上是 SV *
。
gv_fetchmethod
和 perl_call_sv
函式 gv_fetchmethod
可以像在 Perl 5.003 中一樣找到一個物件的方法。它返回的 GV 可能是一個方法快取項目。然而,在 Perl 5.004 中,方法快取項目對使用者是不可見的;因此,它們不能直接傳遞給 perl_call_sv
。相反,您應該使用 GvCV
宏在 GV 上提取其 CV,並將 CV 傳遞給 perl_call_sv
。
將 gv_fetchmethod
的結果傳遞給 perl_call_sv
的最可能症狀是 Perl 在對給定方法進行第二次呼叫時產生 "Undefined subroutine called" 錯誤(因為第一次呼叫時沒有快取)。
perl_eval_pv
這是一個在 C 代碼中 eval 字串 Perl 代碼的方便函式。該函式返回 eval 陳述的值,可以用來代替從符號表中提取全域變量。有關詳細信息和示例,請參見 perlguts、perlembed 和 perlcall。
哈希鍵的內部處理已更改。舊的 hashtable API 仍然得到完全支持,並且可能會一直保持這樣。API 的擴展允許將鍵作為 SV*
進行傳遞,因此 tied
哈希可以將真正的標量作為鍵,而不是普通字符串(非綁定的哈希仍然只能使用字符串作為鍵)。如果新的擴展希望使用 SV*
鍵,則必須使用新的哈希訪問函數和宏。這些擴展也使操作 HE*
(哈希條目)變得可行,這可能更有效。詳情請參見 perlguts。
許多基本和庫的 pod 文件已更新。這些新的 pod 文件包含在第 1 節中。
這個文件。
常見問題。
區域支持(國際化和本地化)。
Perl 面向對象編程的教程。
Perl 內部 IO 抽象接口。
Perl 模組庫及建議的模組創建實踐。從perlmod中提取(結果更小)。
雖然不是新功能,但已大幅更新。
雖然不是新功能,但已大幅更新。
多個新條件將觸發以前沉默的警告。有些僅影響特定平台。以下是這些新警告和錯誤的概述。這些消息分類如下(按絕望程度遞增排列)
(W) A warning (optional).
(D) A deprecation (optional).
(S) A severe warning (mandatory).
(F) A fatal error (trappable).
(P) An internal error you should never see (trappable).
(X) A very fatal error (nontrappable).
(A) An alien error message (not generated by Perl).
(W) 在同一作用域中重新宣告了一個詞彙變數,從而有效地消除了對先前實例的所有訪問權限。這幾乎總是一個排字錯誤。請注意,早期的變數仍將存在,直到作用域結束或直到所有對其的閉包參照被銷毀為止。
(F) delete() 的參數必須是哈希元素,例如
$foo{$bar}
$ref->[12]->{"susie"}
或哈希片段,例如
@foo{$bar, $baz, $xyzzy}
@{$ref->[12]}{"susie", "queue"}
(X) 在 MS-DOS 機器上無法分配超過 64K。
(F) 不能分配超過 2^31+"small amount" 個字節。
(W) 模式匹配(//)、替換(s///)和轉譯(tr///)運算符僅適用於純量值。如果將其中之一應用於數組或哈希,它將將數組或哈希轉換為純量值(數組的長度或哈希的填充信息),然後對該純量值進行操作。這可能不是您想要做的。請參閱perlfunc 中的 "grep"和"map"進行替代。
(P) Perl 維護一個引用計數的內部字符串表,以優化哈希鍵和其他字符串的存儲和訪問。這表示有人試圖減少表中無法找到的字符串的引用計數。
(W) 您將 substr() 用作 lvalue 的第一個參數提供了一個引用,這相當奇怪。也許您忘了先解引用它。請參見perlfunc 中的 "substr"。
(W) 您使用了形式為 Foo::
的合格裸字,但編譯器在此之前看不到該命名空間的其他用法。也許您需要預先聲明一個套件?
(F) Perl 優化排序子程序的內部處理並保留對它們的指針。當一個這樣的排序子程序當前處於活動狀態時,您嘗試重新定義它,這是不允許的。如果您真的想這樣做,您應該寫 sort { &func } @x
而不是 sort func @x
。
(F) "strict refs" 只允許硬引用。符號引用是被禁止的。請參見perlref。
(P) 嘗試解析由方法名指定的重載時發生內部錯誤(而不是子程序引用)。
(S) 您重新定義了先前適合內嵌的子程序。請參見perlsub 中的 "Constant Functions"進行評論和解決方法。
(S) 您取消定義了先前適合內嵌的子程序。請參見perlsub 中的 "Constant Functions"進行評論和解決方法。
(F) 重載 "=" 的方法有問題。請參見overload 中的 "Copy Constructor"。
(F)您給 die() 傳遞了一個空字符串(相當於 die ""
),或者您調用它時沒有傳遞參數,而 $@
和 $_
都是空的。
(W)您正在以非傳統的方式退出一個相當特殊的區塊結構(例如排序區塊或子程序),例如使用 goto 或循環控制語句。參見 perlfunc 中的 "sort"。
(F)對於簡單名稱,Perl 將標識符(變量名稱、函數名稱等)限制為 252 個字符,對於複合名稱(例如 $A::B
)限制稍高。您已超出 Perl 的限制。未來版本的 Perl 可能會消除這些任意限制。
(F)輸入中發現了換行符。這是一個錯誤,而不是一個警告,因為換行符可能會破壞多行字符串,包括這裡的文檔(例如 print <<EOF;
)。
(X)PERL5OPT 環境變量僅可用於設置以下開關:-[DIMUdmw]。
(S)您指定的十六進制數字文字太大,超出了您的架構範圍。在 32 位架構上,最大的十六進制文字為 0xFFFFFFFF。
(S)您指定的八進制數字文字太大,超出了您的架構範圍。在 32 位架構上,最大的八進制文字為 037777777777。
(P)在 glob
和 <*.c>
的外部程序中發生了問題。這可能意味著您的 csh(C shell)出現了問題。如果是這樣,您應該更改 config.sh 中的所有 csh 相關變量:如果您有 tcsh,則使變量參考它,如同它是 csh(例如 full_csh='/usr/bin/tcsh'
);否則,使它們全部為空(除了 d_csh
應該是 'undef'
),這樣 Perl 將會認為 csh 遺失。無論哪種情況,在編輯完 config.sh 後,運行 ./Configure -S
並重新構建 Perl。
(W)Perl無法理解給定的格式轉換。請參閱perlfunc中的 "sprintf"。
(F)給定的字符不是有效的封裝類型。請參閱perlfunc中的 "pack"。
(F)給定的字符不是有效的解封裝類型。請參閱perlfunc中的 "unpack"。
(W)排版錯誤通常表現為唯一的變數名稱。如果您有一個使用唯一名稱的充分理由,那麼只需以某種方式再次提及它以抑制消息("use vars" 声明是為此目的提供的)。
(F)formline 的第一個參數必須是有效的格式圖片規範。它被發現為空,這可能意味著您提供了未初始化的值。請參閱perlform。
(F)您嘗試使用指向緩衝區外部的偏移進行讀取/寫入/發送/接收操作。這很難想象。唯一的例外是,sysread() 超出緩衝區將擴展緩衝區並對新區域進行零填充。
(X|F)malloc() 函数返回 0,表示沒有足夠的剩餘內存(或虛擬內存)滿足請求。
請求被判定為小型,因此捕獲它的可能性取決於 Perl 的編譯方式。默認情況下,它不可捕獲。但是,如果為此進行了編譯,Perl 可能在使用此消息 die() 後使用 $^M 的內容作為緊急池。在這種情況下,錯誤是可捕獲的 一次。
(F)malloc() 函数返回 0,表示沒有足夠的剩餘內存(或虛擬內存)滿足請求。但是,被判定為足夠大(編譯時默認值為 64K),因此可以通過捕獲此錯誤來關閉的可能性。
(P)庫函數 frexp() 失敗,使 printf("%f") 不可能。
(W) qw() 列表包含由空白分隔的項目;與文字字串一樣,註釋字符不會被忽略,而是被視為字面資料。 (您可能使用了不同於此處所示的括號的分隔符號;大括號也常用。)
您可能寫了類似這樣的東西
@list = qw(
a # a comment
b # another comment
);
但您應該寫成這樣
@list = qw(
a
b
);
如果您真的需要註釋,請以引號和逗號的方式建立您的列表
@list = (
'a', # a comment
'b', # another comment
);
(W) qw() 列表包含由空白分隔的項目;因此不需要逗號來分隔項目。 (您可能使用了不同於此處所示的括號的分隔符號;大括號也常用。)
您可能寫了類似這樣的東西
qw! a, b, c !;
這會將字面逗號放入某些列表項目中。如果您不希望它們出現在您的資料中,請不要使用逗號
qw! a b c !;
(W) 您使用了哈希切片(由 @ 標識)來選擇哈希的單個元素。通常更好地要求標量值(由 $ 標識)。 差異在於 $foo{&bar}
總是像標量一樣行為,無論您是將其賦值還是在評估其引數時,而 @foo{&bar}
在您將其賦值時行為像列表,並且向其下標提供列表上下文,如果您期望只有一個下標,這可能會產生奇怪的事情。
(P) 在 @ISA 樹中的重載解析可能被導入存根破壞。 存根不應該被隱式創建,但對 can
的顯式調用可能會破壞這一點。
(X) Perl 腳本中的 #! 行(或等效的本地行)包含了 -T 選項,但 Perl 在其引數列表中未以 -T 被調用。 這是一個錯誤,因為當 Perl 發現腳本中的 -T 時,已經太遲來正確地從環境中駭取一切。 所以 Perl 放棄了。
(W) 在調用 untie
時,從 tie
(或 tied
)返回的物件的副本仍然有效。
(F)Perl 解析器對於 Perl 腳本(或 eval)中指定的字符不知所措。也許您試圖運行壓縮腳本、二進制程序或目錄作為 Perl 程序。
(F)您的可執行版本不支援分叉。
請注意,在某些系統(如 OS/2)下,可能會有不同版本的 Perl 可執行文件,其中一些可能支援 fork,而另一些則不支援。請嘗試將您呼叫 Perl 的名稱更改為 perl_
、perl__
等。
(D)Perl 5.004 之前的版本錯誤地將任何後接 "$" 和數字的類型標記解讀為 "${$}0" 而不是 "${$0}"。例如,"$0" 被錯誤地解讀為 "${$}0" 而不是 "${$0}"。這個錯誤在 Perl 5.004 中(大部分)被修復。
然而,Perl 5.004的開發者無法完全修復這個錯誤,因為至少有兩個廣泛使用的模組依賴於在字串中"$<digit>"的舊含義。因此,Perl 5.004在字串內部仍然像舊的(錯誤的)方式解釋"$<digit>",但它會生成此警告訊息。在Perl 5.005中,這種特殊處理將停止。
(W)在條件表達式中,您使用了 <HANDLE>、<*>(glob)、each()
或 readdir()
作為布林值。這些構造中的每一個都可能返回值 "0";這將使條件表達式為假,這可能不是您想要的。在條件表達式中使用這些構造時,請使用 defined
運算符測試它們的值。
(W)一個內部(嵌套的)匿名子例程位於一個命名子例程內部,並且在外部還有另一個例程;而這個匿名(最內層)子例程正在引用在最外層子例程中定義的一個詞法變量。例如
sub outermost { my $a; sub middle { sub { $a } } }
如果匿名子例程從最外層子例程中被直接或間接地調用或引用,它將與共享變數共享,就像您所期望的那樣。但是如果匿名子例程在最外層子例程不活動時被調用或引用,它將會看到共享變數的值,就像在第一次調用最外層子例程時的值一樣,這可能不是您想要的。
在這些情況下,通常最好將中間的子程序設為匿名,使用 sub {}
語法。Perl 對於嵌套匿名子程序中的共享變量有特定支援;命名的子程序會干擾此功能。
(W) 內部(嵌套的)命名 子程序正在引用外部子程序中定義的詞法變量。
當內部子程序被調用時,它可能會看到外部子程序的變量值,就像它在外部子程序的第一次調用之前和期間看到的一樣;在這種情況下,在外部子程序的第一次調用完成後,內部和外部子程序將不再共享變量的共同值。換句話說,該變量將不再共享。
此外,如果外部子程序是匿名的並且引用了自身之外的詞法變量,則外部和內部子程序將永遠不會共享給定的變量。
通常,可以通過將內部子程序設為匿名,使用 sub {}
語法來解決此問題。當內部匿名子程序引用外部子程序中的變量被調用或引用時,它們將自動重新綁定到這些變量的當前值。
(W) 你向 warn() 傳遞了一個空字符串(相當於 warn ""
)或者你沒有傳遞參數並且 $_
是空的。
(W) 一個特有於 VMS 的警告。在準備對 %ENV 進行迭代時遇到了一個邏輯名稱,該邏輯名稱違反了管理邏輯名稱的語法規則。由於無法正常翻譯,因此它被跳過,並且不會出現在 %ENV 中。這可能是一個無害的事件,因為一些軟件包可能直接修改邏輯名稱表並引入非標準名稱,或者它可能表示邏輯名稱表已損壞。
(P) OS/2 專用的錯誤。很可能您正在使用過時的 Perl 版本,但無論如何都不應該發生這種情況。
(F) OS/2 專用的錯誤。PERLLIB_PREFIX 應該是以下形式之一:
prefix1;prefix2
或
prefix1 prefix2
其中 prefix1 和 prefix2 都是非空的前綴。如果 prefix1
確實是內置庫搜索路徑的前綴,則會替換 prefix2。如果找不到組件或組件過長,則可能會出現此錯誤。請參閱 README.os2 中的 "PERLLIB_PREFIX"。
(F) OS/2 專用的錯誤。PERL_SH_DIR 是尋找 sh
shell 的目錄。請參閱 README.os2 中的 "PERL_SH_DIR"。
(W) 這是 OS/2 應用程序發出的標準消息,而 *nix 應用程序則默默死亡。這被認為是 OS/2 版本的一個功能。可以通過適當的信號處理程序輕鬆禁用此功能,請參閱 perlipc 中的 "Signals"。另請參閱 README.os2 中的 "Process terminated by SIGTERM/SIGINT"。
如果您認為發現了一個 bug,您可以檢查 comp.lang.perl.misc 新聞組中最近發表文章的標題。您還可以在 http://www.perl.com/perl/,即 Perl 官方網站上找到相關信息。
如果您認為自己發現了一個未報告的 bug,請運行隨您版本一同提供的 perlbug 程序。請確保將您的 bug 減少到一個小但足夠的測試案例。您的 bug 报告連同 perl -V
的輸出將被發送至 <perlbug@perl.com>,由 Perl 移植團隊進行分析。
詳細的更改信息請參閱 Changes 文件。
如何構建 Perl 的方法請參閱 INSTALL 文件。對於 5.004 版本,此文件已經進行了重大更新,因此即使是老用戶也應該仔細閱讀。
一般信息請參閱 README 文件。
版權信息請參閱 Copying 文件。
由 Tom Christiansen 構建,取得了無數貢獻者的許可,並經過許多 Perl 開發人員的建議。
最後更新時間:1997年5月14日週三,東部夏令時間上午11:14:09