単なる誤植だと思われ

CGIプログラミング第2版は読んだことないけど
URLエンコードならその正規表現の直後にtrでスペースはを+にしてるんでしょ?
こんな感じで
$text =~ s/([^a-z0-9_.!~*'\(\) -])/sprintf "%%%02X", ord($1)/egi;
$text =~ tr/ /+/;