perlebcdic - 在 EBCDIC 平台上執行 Perl 的考量
探討 Perl 程式設計師在使用 EBCDIC 電腦時會遇到的部分問題。
此文件尚未完工的部分已標記為 XXX。
早期 Perl 版本可在部分 EBCDIC 電腦上執行,但已知最後一個可在 EBCDIC 上執行的版本為 v5.8.7,直到 v5.22,Perl 核心才又可在 z/OS 上執行。理論上,它可以在 OS/400 或 Siemens' BS2000(或其後繼版本)上執行,但這尚未經過測試。在 v5.22 和 5.24 中,並非所有在 CPAN 上找到但與核心 Perl 一起發布的模組都可以在 z/OS 上執行。
如果您想在非 z/OS EBCDIC 電腦上使用 Perl,請透過 https://github.com/Perl/perl5/issues 告知我們。
在 EBCDIC 平台上撰寫 Perl 程式與在 "ASCII" 平台上撰寫程式並無不同,但底層數字不同,我們稍後會說明。您必須了解這些 "ASCII" 平台,因為文件有偏見,而且經常會使用不適用於 EBCDIC 的範例數字。此外,很少有 CPAN 模組是專門為 EBCDIC 編寫且無法在 ASCII 上執行的;相反地,絕大多數 CPAN 模組都是為 ASCII 編寫,有些可能碰巧可以在 EBCDIC 上執行,而少數模組則設計為可以在兩者上執行。
如果您的程式碼僅使用 52 個字母 A-Z 和 a-z,加上空白鍵、數字 0-9,以及 Perl 使用的標點符號,加上一些由跳脫序列表示的控制字元,例如 \n
和 \t
,那麼使用 Perl 沒有什麼特別之處,而且您的程式碼很可能可以在 ASCII 電腦上執行,而不需要變更。
但是,如果您撰寫的程式碼使用 \005
表示 TAB 或 \xC1
表示 "A",或 \xDF
表示 "ÿ"(帶分音符的小寫 "y"),那麼您的程式碼很可能可以在您的 EBCDIC 平台上執行,但無法在 ASCII 平台上執行。如果沒有人會在 ASCII 平台上執行您的程式碼,這樣做是可以的;但本文檔的偏見在於撰寫可在 EBCDIC 和 ASCII 系統之間移植的程式碼。同樣地,如果您關心的每個字元都可以輕鬆從鍵盤輸入,您不需要了解任何 ASCII,但許多鍵盤無法讓您直接輸入字元,例如 \xDF
,因此您必須間接指定它,例如使用 "\xDF"
跳脫序列。在這種情況下,最簡單的方法是了解一些 ASCII/Unicode 字元集。如果您知道小寫 "ÿ" 是 U+00FF
,那麼您可以將其指定為 "\N{U+FF}"
,並讓電腦自動將其轉換為您平台上的 \xDF
,並將其保留為 ASCII 平台上的 \xFF
。或者,您可以透過名稱指定它,\N{LATIN SMALL LETTER Y WITH DIAERESIS
,而不需要知道數字。這兩種方法都可以,但都需要熟悉 Unicode。
美國資訊交換標準碼(ASCII 或 US-ASCII)是一組從 0 到 127(十進位)的整數,這些整數由使用 ASCII 的電腦標準化詮釋。例如,65 表示字母「A」。範圍 0..127 可透過設定 7 位元二進制數字中的各種位元來涵蓋,因此該組有時稱為「7 位元 ASCII」。ASCII 由美國國家標準協會文件 ANSI X3.4-1986 描述。它也由 ISO 646:1991 描述(包含貨幣符號的在地化)。完整的 ASCII 組在 下方的表格中給出,為前 128 個元素。可以用 ASCII 中的字元充分書寫的語言包括英語、夏威夷語、印尼語、斯瓦希里語和一些美洲原住民語言。
大多數非 EBCDIC 字元集都是 ASCII 的超集。也就是說,整數 0-127 表示 ASCII 所說的意義。但整數 128 以上則特定於字元集。
其中許多完全符合 8 位元,使用 ASCII 作為 0-127,同時指定 128-255 的意義,且不使用 255 以上的任何內容。因此,這些是單位元組(或如果您喜歡,是八位元組)字元集。一個重要的字元集(因為 Unicode 是它的超集)是 ISO 8859-1 字元集。
ISO 8859-$n 是國際標準化組織 (ISO) 的一組字元編碼集,每個字元編碼集都會將字元新增到 ASCII 組中,這些字元通常出現在各種語言中,其中許多基於羅馬字母或拉丁字母。大多數是歐洲語言,但也有阿拉伯語、希臘語、希伯來語和泰語。網路上有關於所有這些的良好參考。
ASCII 的特定 8 位元延伸,包括重音符和銳音符的拉丁字母。可以使用 ISO 8859-1 的語言包括 ASCII 涵蓋的所有語言,以及南非語、阿爾巴尼亞語、巴斯克語、加泰隆尼亞語、丹麥語、法羅語、芬蘭語、挪威語、葡萄牙語、西班牙語和瑞典語。荷蘭語涵蓋在內,但沒有 ij 連字。法語也涵蓋在內,但沒有 oe 連字。德語可以使用 ISO 8859-1,但必須在沒有德語式引號的情況下使用。此組基於 ASCII 的西歐延伸,且在萬維網工作中很常見。在 IBM 字元編碼集識別術語中,ISO 8859-1 也稱為 CCSID 819(或有時稱為 0819 甚至 00819)。
延伸二進制編碼十進制交換碼是指一大組單位元組和多位元組編碼字元集,這些字元集與 ASCII 和 ISO 8859-1 非常不同,而且彼此之間都略有不同;它們通常在主機電腦上執行。EBCDIC 編碼源自霍勒斯穿孔卡編碼的 8 位元組延伸,這遠早於 ASCII。卡片上的配置使得高位元設定為大小寫字母字元 [a-z]
和 [A-Z]
,但在每個拉丁字母範圍內都有間隙,在 下方的表格中可見。這些間隙可能會造成複雜性。
有些 IBM EBCDIC 字元組可能已透過字元組識別碼編號 (CCSID 編號) 或程式碼頁編號而為人所知。
Perl 可在執行下列三種常見 EBCDIC 字元組的平台上編譯。
在 IBM EBCDIC 字元組識別碼編號中,有 13 個字元通常會對應到不同的整數值。這些字元稱為 13 個「變異」字元,而且是
\ [ ] { } ^ ~ ! # | $ @ `
當 Perl 為某個平台編譯時,它會查看所有這些字元以猜測該平台使用的 EBCDIC 字元組,並根據該平台適當地調整自己。如果該平台使用的字元組不是 Perl 所知的這三種字元組之一,Perl 將會無法編譯,或錯誤地且靜默地選擇這三種字元組之一。
換行符號 (LF) 字元實際上是第 14 個變異字元,而且 Perl 也會檢查它。
字元組識別碼編號 0037 是 ASCII 加上拉丁文-1 字元 (即 ISO 8859-1) 對應到 EBCDIC 組的對應。0037 用於在執行於 AS/400 電腦上的 OS/400 作業系統上的北美英語地區設定。CCSID 0037 在 236 個地方與 ISO 8859-1 不同;換句話說,它們只在 20 個碼點值上相同。
字元組識別碼編號 1047 也是 ASCII 加上拉丁文-1 字元 (即 ISO 8859-1) 對應到 EBCDIC 組的對應。1047 用於 OS/390 或 z/OS 的 Unix System Services,以及 VM/ESA 的 OpenEdition。CCSID 1047 在八個地方與 CCSID 0037 不同,而且在 236 個地方與 ISO 8859-1 不同。
在 Siemens' BS2000 系統上使用的 EBCDIC 程式碼頁與 1047 和 0037 不同。它在下方被識別為 POSIX-BC 組。與 0037 和 1047 一樣,它在 20 個碼點值上與 ISO 8859-1 相同。
在 Unicode 術語中,碼點是指定給字元的數字:例如,在 EBCDIC 中,字元「A」通常指定數字 193。在 Unicode 中,字元「A」指定數字 65。ASCII 和拉丁文-1 (ISO 8859-1) 中的所有碼點在 Unicode 中具有相同的意義。所有三個已辨識的 EBCDIC 字元組都有 256 個碼點,而且在每個字元組中,所有 256 個碼點都對應到等效的 Latin1 碼點。顯然地,「A」會對應到「A」、「B」=>「B」、「%」=>「%」等,適用於 Latin1 和這些程式碼頁中的所有可列印字元。
事實證明,EBCDIC 幾乎有 ASCII/Latin1 C0 控制項和 DELETE 控制項的精確等效項。(C0 控制項是其 ASCII 碼點為 0..0x1F 的控制項;例如 TAB、ACK、BEL 等。)在這些 ASCII/EBCDIC 控制項之間設定了對應。在 ASCII 平台上的 C1 控制項和其餘的 EBCDIC 控制項之間沒有如此精確的對應。所作的動作是將這些控制項(大多數是任意地)對應到另一個字元組中其他未匹配的字元。大多數這些控制項現在在 EBCDIC 中很少使用,而且它們的名稱已在沒有太多抱怨的情況下被捨棄。例如,EO (八個一) EBCDIC 控制項(由八個一組成 = 0xFF)對應到 C1 APC 控制項 (0x9F),而且您無法使用名稱「EO」。
EBCDIC 控制項提供三個可能的行終止字元,CR (0x0D)、LF (0x25) 和 NL (0x15)。在 ASCII 平台上,「NL」和「LF」符號指的是同一個字元,但在嚴格的 EBCDIC 術語中,它們是不同的。EBCDIC NL 會對應到稱為「NEL」的 C1 控制項(「下一行」;這裡是對應很有道理的一個案例,因此並非只是隨意的)。在某些 EBCDIC 平台上,這個 NL 或 NEL 是典型的行終止字元。z/OS 和 BS2000 就是如此。在這些平台上,C 編譯器會交換 LF 和 NEL 程式碼點,因此 "\n"
是 0x15,並指涉 NL。Perl 也會這樣做;您可以在 下方的 程式碼圖表中看到。這會讓事情通常「正常運作」,而您甚至不需要知道有交換這件事。
UTF 代表「Unicode 轉換格式」。UTF-8 是 Unicode 編碼成一連串 8 位元組塊的編碼,基於 ASCII 和 Latin-1。表示 Unicode 程式碼點所需的序列長度取決於該程式碼點的序號,數字越大需要的位元組越多。UTF-EBCDIC 類似於 UTF-8,但基於 EBCDIC。它們很類似,因此在一般用法中,這兩個術語會混為一談,並使用「UTF-8」來表示在 ASCII 平台上找到的 UTF-8,以及在 EBCDIC 平台上找到的 UTF-EBCDIC。
您可能會看到「不變」字元或程式碼點這個術語。這只表示當以 UTF-8(或 UTF-EBCDIC)編碼時,字元的數字值和表示法與未編碼時相同。(請注意,這與上面提到的 「13 個變異字元」 是非常不同的概念。謹慎的文字會使用「UTF-8 不變」這個術語,而不是只用「不變」,但您最常只會看到「不變」。)例如,「A」的序號在大部分 EBCDIC 編碼頁中為 193,在以 UTF-EBCDIC 編碼時也是 193。所有 UTF-8(或 UTF-EBCDIC)變異程式碼點在以 UTF-8(或 UTF-EBCDIC)編碼時,會佔用至少兩個位元組;根據定義,UTF-8(或 UTF-EBCDIC)不變程式碼點在以 UTF-8(或 UTF-EBCDIC)編碼時,或未編碼時,只會佔用一個位元組。(現在您知道為什麼人們通常只在說「UTF-8」時,也表示「UTF-EBCDIC」。在本文檔的其餘部分,我們大多也會這樣隨意。)在 ASCII UTF-8 中,對應於最低 128 個序號(0 - 127:ASCII 字元)的程式碼點是不變的。在 UTF-EBCDIC 中,有 160 個不變字元。(如果您想知道,EBCDIC 不變字元是那些有 ASCII 等效字元的字元,加上那些對應於 C1 控制項的字元(在 ASCII 平台上為 128 - 159)。)
以 UTF-EBCDIC 編碼的字串可能會比以 UTF-8 編碼的字串長(極少情況下會較短)。Perl 延伸了 UTF-8 和 UTF-EBCDIC,以便它們可以編碼高於 Unicode 最大值 U+10FFFF 的碼點。這兩個延伸都是建構來允許編碼任何符合 64 位元組字元的碼點。
UTF-EBCDIC 是由 Unicode 技術報告 #16(通常簡稱為 TR16)定義的。它是根據 CCSID 1047 定義的,不允許其他程式碼頁的差異。這允許在執行不同程式碼頁的電腦之間輕鬆交換文字,但對於在這些其他程式碼頁上執行 Perl,則無法使用,除非進行調整。
無法使用的理由是 Perl 的一個基本假設是,它在分析和詞彙分析時所關心的字元,無論文字是否以 UTF-8 編碼,都是相同的。例如,Perl 預期字元 "["
具有相同的表示方式,無論包含它的字串(或程式碼文字)是否以 UTF-8 編碼。為了確保這一點,Perl 會將 UTF-EBCDIC 調整到特定的程式碼頁,以便它預期為 UTF-8 不變的所有字元實際上都是 UTF-8 不變的。這表示在執行 Perl 的 UTF-EBCDIC 其中一個版本的電腦上產生的文字,必須轉換才能讓執行另一個版本的電腦理解。
TR16 暗示了一種方法,可以將 UTF-EBCDIC 延伸到編碼高達 2 ** 31 - 1
的點。Perl 對高達 2 ** 30 - 1
的碼點使用此方法,但對較大的碼點使用不相容的方法,以使其能夠處理比其他方法大得多的碼點。
從 Perl 5.8 開始,您可以使用標準模組編碼從 EBCDIC 轉換為 Latin-1 碼點。編碼知道比 Perl 目前可以編譯執行的更多的 EBCDIC 字元集。
use Encode 'from_to';
my %ebcdic = ( 176 => 'cp37', 95 => 'cp1047', 106 => 'posix-bc' );
# $a is in EBCDIC code points
from_to($a, $ebcdic{ord '^'}, 'latin1');
# $a is ISO 8859-1 code points
並從 Latin-1 碼點轉換為 EBCDIC 碼點
use Encode 'from_to';
my %ebcdic = ( 176 => 'cp37', 95 => 'cp1047', 106 => 'posix-bc' );
# $a is ISO 8859-1 code points
from_to($a, 'latin1', $ebcdic{ord '^'});
# $a is in EBCDIC code points
建議您使用 PerlIO 的自動轉換功能來執行 I/O,請參閱 perluniintro。
自版本 5.8 以來,Perl 使用 PerlIO I/O 函式庫。這使您可以對每個 IO 通道使用不同的編碼。例如,您可以使用
use Encode;
open($f, ">:encoding(ascii)", "test.ascii");
print $f "Hello World!\n";
open($f, ">:encoding(cp37)", "test.ebcdic");
print $f "Hello World!\n";
open($f, ">:encoding(latin1)", "test.latin1");
print $f "Hello World!\n";
open($f, ">:encoding(utf8)", "test.utf8");
print $f "Hello World!\n";
取得四個包含「Hello World!\n」的檔案,分別以 ASCII、CP 0037 EBCDIC、ISO 8859-1(Latin-1)(在此範例中與 ASCII 相同,因為只印出 ASCII 字元)和 UTF-EBCDIC(在此範例中與一般 EBCDIC 相同,因為只印出 EBCDIC 和 UTF-EBCDIC 之間沒有差異的字元)。有關詳細資訊,請參閱 Encode::PerlIO 的文件。
由於 PerlIO 層在內部使用原始 IO(位元組),因此這完全忽略了檔案系統類型(ASCII 或 EBCDIC)等事項。
下列表格列出 ASCII 和 Latin 1 排序的集合,包括子集合:C0 控制碼 (0..31)、ASCII 繪圖字元 (32..7e)、刪除 (7f)、C1 控制碼 (80..9f) 和 Latin-1 (又稱 ISO 8859-1) (a0..ff)。在表格名稱中,ASCII 的 Latin 1 延伸字元已標示為字元名稱,大致對應於《Unicode 標準,第 6.1 版》,儘管在所有情況下都以替換為準,例如 s/LATIN//
和 s/VULGAR//
;在某些情況下為 s/CAPITAL LETTER//
;在某些其他情況下為 s/SMALL LETTER ([A-Z])/\l$1/
。控制碼使用 Unicode 6.2 縮寫列出。0037 和 1047 集合之間的差異標示為 **
。1047 和 POSIX-BC 集合之間的差異標示為 ##.
所有列出的 ord()
數字均為十進位。如果您想查看此表格列出的八進位值,請執行表格(也就是此文件的 pod 原始文字,因為此食譜可能無法與 pod2_other_format 翻譯搭配使用)
perl -ne 'if(/(.{29})(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/)' \
-e '{printf("%s%-5.03o%-5.03o%-5.03o%.03o\n",$1,$2,$3,$4,$5)}' \
perlebcdic.pod
如果您想保留 UTF-x 碼點,則在指令碼形式中,您可能想寫
open(FH,"<perlebcdic.pod") or die "Could not open perlebcdic.pod: $!";
while (<FH>) {
if (/(.{29})(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\.?(\d*)
\s+(\d+)\.?(\d*)/x)
{
if ($7 ne '' && $9 ne '') {
printf(
"%s%-5.03o%-5.03o%-5.03o%-5.03o%-3o.%-5o%-3o.%.03o\n",
$1,$2,$3,$4,$5,$6,$7,$8,$9);
}
elsif ($7 ne '') {
printf("%s%-5.03o%-5.03o%-5.03o%-5.03o%-3o.%-5o%.03o\n",
$1,$2,$3,$4,$5,$6,$7,$8);
}
else {
printf("%s%-5.03o%-5.03o%-5.03o%-5.03o%-5.03o%.03o\n",
$1,$2,$3,$4,$5,$6,$8);
}
}
}
如果您想查看此表格列出的十六進位值,請執行表格
perl -ne 'if(/(.{29})(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/)' \
-e '{printf("%s%-5.02X%-5.02X%-5.02X%.02X\n",$1,$2,$3,$4,$5)}' \
perlebcdic.pod
或者,為了保留十六進位的 UTF-x 碼點
open(FH,"<perlebcdic.pod") or die "Could not open perlebcdic.pod: $!";
while (<FH>) {
if (/(.{29})(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\.?(\d*)
\s+(\d+)\.?(\d*)/x)
{
if ($7 ne '' && $9 ne '') {
printf(
"%s%-5.02X%-5.02X%-5.02X%-5.02X%-2X.%-6.02X%02X.%02X\n",
$1,$2,$3,$4,$5,$6,$7,$8,$9);
}
elsif ($7 ne '') {
printf("%s%-5.02X%-5.02X%-5.02X%-5.02X%-2X.%-6.02X%02X\n",
$1,$2,$3,$4,$5,$6,$7,$8);
}
else {
printf("%s%-5.02X%-5.02X%-5.02X%-5.02X%-5.02X%02X\n",
$1,$2,$3,$4,$5,$6,$8);
}
}
}
ISO
8859-1 POS- CCSID
CCSID CCSID CCSID IX- 1047
chr 0819 0037 1047 BC UTF-8 UTF-EBCDIC
---------------------------------------------------------------------
<NUL> 0 0 0 0 0 0
<SOH> 1 1 1 1 1 1
<STX> 2 2 2 2 2 2
<ETX> 3 3 3 3 3 3
<EOT> 4 55 55 55 4 55
<ENQ> 5 45 45 45 5 45
<ACK> 6 46 46 46 6 46
<BEL> 7 47 47 47 7 47
<BS> 8 22 22 22 8 22
<HT> 9 5 5 5 9 5
<LF> 10 37 21 21 10 21 **
<VT> 11 11 11 11 11 11
<FF> 12 12 12 12 12 12
<CR> 13 13 13 13 13 13
<SO> 14 14 14 14 14 14
<SI> 15 15 15 15 15 15
<DLE> 16 16 16 16 16 16
<DC1> 17 17 17 17 17 17
<DC2> 18 18 18 18 18 18
<DC3> 19 19 19 19 19 19
<DC4> 20 60 60 60 20 60
<NAK> 21 61 61 61 21 61
<SYN> 22 50 50 50 22 50
<ETB> 23 38 38 38 23 38
<CAN> 24 24 24 24 24 24
<EOM> 25 25 25 25 25 25
<SUB> 26 63 63 63 26 63
<ESC> 27 39 39 39 27 39
<FS> 28 28 28 28 28 28
<GS> 29 29 29 29 29 29
<RS> 30 30 30 30 30 30
<US> 31 31 31 31 31 31
<SPACE> 32 64 64 64 32 64
! 33 90 90 90 33 90
" 34 127 127 127 34 127
# 35 123 123 123 35 123
$ 36 91 91 91 36 91
% 37 108 108 108 37 108
& 38 80 80 80 38 80
' 39 125 125 125 39 125
( 40 77 77 77 40 77
) 41 93 93 93 41 93
* 42 92 92 92 42 92
+ 43 78 78 78 43 78
, 44 107 107 107 44 107
- 45 96 96 96 45 96
. 46 75 75 75 46 75
/ 47 97 97 97 47 97
0 48 240 240 240 48 240
1 49 241 241 241 49 241
2 50 242 242 242 50 242
3 51 243 243 243 51 243
4 52 244 244 244 52 244
5 53 245 245 245 53 245
6 54 246 246 246 54 246
7 55 247 247 247 55 247
8 56 248 248 248 56 248
9 57 249 249 249 57 249
: 58 122 122 122 58 122
; 59 94 94 94 59 94
< 60 76 76 76 60 76
= 61 126 126 126 61 126
> 62 110 110 110 62 110
? 63 111 111 111 63 111
@ 64 124 124 124 64 124
A 65 193 193 193 65 193
B 66 194 194 194 66 194
C 67 195 195 195 67 195
D 68 196 196 196 68 196
E 69 197 197 197 69 197
F 70 198 198 198 70 198
G 71 199 199 199 71 199
H 72 200 200 200 72 200
I 73 201 201 201 73 201
J 74 209 209 209 74 209
K 75 210 210 210 75 210
L 76 211 211 211 76 211
M 77 212 212 212 77 212
N 78 213 213 213 78 213
O 79 214 214 214 79 214
P 80 215 215 215 80 215
Q 81 216 216 216 81 216
R 82 217 217 217 82 217
S 83 226 226 226 83 226
T 84 227 227 227 84 227
U 85 228 228 228 85 228
V 86 229 229 229 86 229
W 87 230 230 230 87 230
X 88 231 231 231 88 231
Y 89 232 232 232 89 232
Z 90 233 233 233 90 233
[ 91 186 173 187 91 173 ** ##
\ 92 224 224 188 92 224 ##
] 93 187 189 189 93 189 **
^ 94 176 95 106 94 95 ** ##
_ 95 109 109 109 95 109
` 96 121 121 74 96 121 ##
a 97 129 129 129 97 129
b 98 130 130 130 98 130
c 99 131 131 131 99 131
d 100 132 132 132 100 132
e 101 133 133 133 101 133
f 102 134 134 134 102 134
g 103 135 135 135 103 135
h 104 136 136 136 104 136
i 105 137 137 137 105 137
j 106 145 145 145 106 145
k 107 146 146 146 107 146
l 108 147 147 147 108 147
m 109 148 148 148 109 148
n 110 149 149 149 110 149
o 111 150 150 150 111 150
p 112 151 151 151 112 151
q 113 152 152 152 113 152
r 114 153 153 153 114 153
s 115 162 162 162 115 162
t 116 163 163 163 116 163
u 117 164 164 164 117 164
v 118 165 165 165 118 165
w 119 166 166 166 119 166
x 120 167 167 167 120 167
y 121 168 168 168 121 168
z 122 169 169 169 122 169
{ 123 192 192 251 123 192 ##
| 124 79 79 79 124 79
} 125 208 208 253 125 208 ##
~ 126 161 161 255 126 161 ##
<DEL> 127 7 7 7 127 7
<PAD> 128 32 32 32 194.128 32
<HOP> 129 33 33 33 194.129 33
<BPH> 130 34 34 34 194.130 34
<NBH> 131 35 35 35 194.131 35
<IND> 132 36 36 36 194.132 36
<NEL> 133 21 37 37 194.133 37 **
<SSA> 134 6 6 6 194.134 6
<ESA> 135 23 23 23 194.135 23
<HTS> 136 40 40 40 194.136 40
<HTJ> 137 41 41 41 194.137 41
<VTS> 138 42 42 42 194.138 42
<PLD> 139 43 43 43 194.139 43
<PLU> 140 44 44 44 194.140 44
<RI> 141 9 9 9 194.141 9
<SS2> 142 10 10 10 194.142 10
<SS3> 143 27 27 27 194.143 27
<DCS> 144 48 48 48 194.144 48
<PU1> 145 49 49 49 194.145 49
<PU2> 146 26 26 26 194.146 26
<STS> 147 51 51 51 194.147 51
<CCH> 148 52 52 52 194.148 52
<MW> 149 53 53 53 194.149 53
<SPA> 150 54 54 54 194.150 54
<EPA> 151 8 8 8 194.151 8
<SOS> 152 56 56 56 194.152 56
<SGC> 153 57 57 57 194.153 57
<SCI> 154 58 58 58 194.154 58
<CSI> 155 59 59 59 194.155 59
<ST> 156 4 4 4 194.156 4
<OSC> 157 20 20 20 194.157 20
<PM> 158 62 62 62 194.158 62
<APC> 159 255 255 95 194.159 255 ##
<NON-BREAKING SPACE> 160 65 65 65 194.160 128.65
<INVERTED "!" > 161 170 170 170 194.161 128.66
<CENT SIGN> 162 74 74 176 194.162 128.67 ##
<POUND SIGN> 163 177 177 177 194.163 128.68
<CURRENCY SIGN> 164 159 159 159 194.164 128.69
<YEN SIGN> 165 178 178 178 194.165 128.70
<BROKEN BAR> 166 106 106 208 194.166 128.71 ##
<SECTION SIGN> 167 181 181 181 194.167 128.72
<DIAERESIS> 168 189 187 121 194.168 128.73 ** ##
<COPYRIGHT SIGN> 169 180 180 180 194.169 128.74
<FEMININE ORDINAL> 170 154 154 154 194.170 128.81
<LEFT POINTING GUILLEMET> 171 138 138 138 194.171 128.82
<NOT SIGN> 172 95 176 186 194.172 128.83 ** ##
<SOFT HYPHEN> 173 202 202 202 194.173 128.84
<REGISTERED TRADE MARK> 174 175 175 175 194.174 128.85
<MACRON> 175 188 188 161 194.175 128.86 ##
<DEGREE SIGN> 176 144 144 144 194.176 128.87
<PLUS-OR-MINUS SIGN> 177 143 143 143 194.177 128.88
<SUPERSCRIPT TWO> 178 234 234 234 194.178 128.89
<SUPERSCRIPT THREE> 179 250 250 250 194.179 128.98
<ACUTE ACCENT> 180 190 190 190 194.180 128.99
<MICRO SIGN> 181 160 160 160 194.181 128.100
<PARAGRAPH SIGN> 182 182 182 182 194.182 128.101
<MIDDLE DOT> 183 179 179 179 194.183 128.102
<CEDILLA> 184 157 157 157 194.184 128.103
<SUPERSCRIPT ONE> 185 218 218 218 194.185 128.104
<MASC. ORDINAL INDICATOR> 186 155 155 155 194.186 128.105
<RIGHT POINTING GUILLEMET> 187 139 139 139 194.187 128.106
<FRACTION ONE QUARTER> 188 183 183 183 194.188 128.112
<FRACTION ONE HALF> 189 184 184 184 194.189 128.113
<FRACTION THREE QUARTERS> 190 185 185 185 194.190 128.114
<INVERTED QUESTION MARK> 191 171 171 171 194.191 128.115
<A WITH GRAVE> 192 100 100 100 195.128 138.65
<A WITH ACUTE> 193 101 101 101 195.129 138.66
<A WITH CIRCUMFLEX> 194 98 98 98 195.130 138.67
<A WITH TILDE> 195 102 102 102 195.131 138.68
<A WITH DIAERESIS> 196 99 99 99 195.132 138.69
<A WITH RING ABOVE> 197 103 103 103 195.133 138.70
<CAPITAL LIGATURE AE> 198 158 158 158 195.134 138.71
<C WITH CEDILLA> 199 104 104 104 195.135 138.72
<E WITH GRAVE> 200 116 116 116 195.136 138.73
<E WITH ACUTE> 201 113 113 113 195.137 138.74
<E WITH CIRCUMFLEX> 202 114 114 114 195.138 138.81
<E WITH DIAERESIS> 203 115 115 115 195.139 138.82
<I WITH GRAVE> 204 120 120 120 195.140 138.83
<I WITH ACUTE> 205 117 117 117 195.141 138.84
<I WITH CIRCUMFLEX> 206 118 118 118 195.142 138.85
<I WITH DIAERESIS> 207 119 119 119 195.143 138.86
<CAPITAL LETTER ETH> 208 172 172 172 195.144 138.87
<N WITH TILDE> 209 105 105 105 195.145 138.88
<O WITH GRAVE> 210 237 237 237 195.146 138.89
<O WITH ACUTE> 211 238 238 238 195.147 138.98
<O WITH CIRCUMFLEX> 212 235 235 235 195.148 138.99
<O WITH TILDE> 213 239 239 239 195.149 138.100
<O WITH DIAERESIS> 214 236 236 236 195.150 138.101
<MULTIPLICATION SIGN> 215 191 191 191 195.151 138.102
<O WITH STROKE> 216 128 128 128 195.152 138.103
<U WITH GRAVE> 217 253 253 224 195.153 138.104 ##
<U WITH ACUTE> 218 254 254 254 195.154 138.105
<U WITH CIRCUMFLEX> 219 251 251 221 195.155 138.106 ##
<U WITH DIAERESIS> 220 252 252 252 195.156 138.112
<Y WITH ACUTE> 221 173 186 173 195.157 138.113 ** ##
<CAPITAL LETTER THORN> 222 174 174 174 195.158 138.114
<SMALL LETTER SHARP S> 223 89 89 89 195.159 138.115
<a WITH GRAVE> 224 68 68 68 195.160 139.65
<a WITH ACUTE> 225 69 69 69 195.161 139.66
<a WITH CIRCUMFLEX> 226 66 66 66 195.162 139.67
<a WITH TILDE> 227 70 70 70 195.163 139.68
<a WITH DIAERESIS> 228 67 67 67 195.164 139.69
<a WITH RING ABOVE> 229 71 71 71 195.165 139.70
<SMALL LIGATURE ae> 230 156 156 156 195.166 139.71
<c WITH CEDILLA> 231 72 72 72 195.167 139.72
<e WITH GRAVE> 232 84 84 84 195.168 139.73
<e WITH ACUTE> 233 81 81 81 195.169 139.74
<e WITH CIRCUMFLEX> 234 82 82 82 195.170 139.81
<e WITH DIAERESIS> 235 83 83 83 195.171 139.82
<i WITH GRAVE> 236 88 88 88 195.172 139.83
<i WITH ACUTE> 237 85 85 85 195.173 139.84
<i WITH CIRCUMFLEX> 238 86 86 86 195.174 139.85
<i WITH DIAERESIS> 239 87 87 87 195.175 139.86
<SMALL LETTER eth> 240 140 140 140 195.176 139.87
<n WITH TILDE> 241 73 73 73 195.177 139.88
<o WITH GRAVE> 242 205 205 205 195.178 139.89
<o WITH ACUTE> 243 206 206 206 195.179 139.98
<o WITH CIRCUMFLEX> 244 203 203 203 195.180 139.99
<o WITH TILDE> 245 207 207 207 195.181 139.100
<o WITH DIAERESIS> 246 204 204 204 195.182 139.101
<DIVISION SIGN> 247 225 225 225 195.183 139.102
<o WITH STROKE> 248 112 112 112 195.184 139.103
<u WITH GRAVE> 249 221 221 192 195.185 139.104 ##
<u WITH ACUTE> 250 222 222 222 195.186 139.105
<u WITH CIRCUMFLEX> 251 219 219 219 195.187 139.106
<u WITH DIAERESIS> 252 220 220 220 195.188 139.112
<y WITH ACUTE> 253 141 141 141 195.189 139.113
<SMALL LETTER thorn> 254 142 142 142 195.190 139.114
<y WITH DIAERESIS> 255 223 223 223 195.191 139.115
如果您想查看上述表格以 CCSID 0037 順序顯示,而不是 ASCII + Latin-1 順序,請執行表格
perl \
-ne 'if(/.{29}\d{1,3}\s{2,4}\d{1,3}\s{2,4}\d{1,3}\s{2,4}\d{1,3}/)'\
-e '{push(@l,$_)}' \
-e 'END{print map{$_->[0]}' \
-e ' sort{$a->[1] <=> $b->[1]}' \
-e ' map{[$_,substr($_,34,3)]}@l;}' perlebcdic.pod
如果您想以 CCSID 1047 順序查看,請將最後一行的數字 34 變更為 39,如下所示
perl \
-ne 'if(/.{29}\d{1,3}\s{2,4}\d{1,3}\s{2,4}\d{1,3}\s{2,4}\d{1,3}/)'\
-e '{push(@l,$_)}' \
-e 'END{print map{$_->[0]}' \
-e ' sort{$a->[1] <=> $b->[1]}' \
-e ' map{[$_,substr($_,39,3)]}@l;}' perlebcdic.pod
如果您想以 POSIX-BC 順序查看,請將最後一行的數字 34 變更為 44,如下所示
perl \
-ne 'if(/.{29}\d{1,3}\s{2,4}\d{1,3}\s{2,4}\d{1,3}\s{2,4}\d{1,3}/)'\
-e '{push(@l,$_)}' \
-e 'END{print map{$_->[0]}' \
-e ' sort{$a->[1] <=> $b->[1]}' \
-e ' map{[$_,substr($_,44,3)]}@l;}' perlebcdic.pod
自此文件首次撰寫以來,慣例已越來越傾向於使用十六進位表示法表示碼點。要使用食譜執行此操作並進行排序是一個多步驟的程序,因此,為了方便起見,以下是上述表格,已重新排序為使用十六進位表示法,並以 1047 代碼頁順序顯示。
ISO
8859-1 POS- CCSID
CCSID CCSID CCSID IX- 1047
chr 0819 0037 1047 BC UTF-8 UTF-EBCDIC
---------------------------------------------------------------------
<NUL> 00 00 00 00 00 00
<SOH> 01 01 01 01 01 01
<STX> 02 02 02 02 02 02
<ETX> 03 03 03 03 03 03
<ST> 9C 04 04 04 C2.9C 04
<HT> 09 05 05 05 09 05
<SSA> 86 06 06 06 C2.86 06
<DEL> 7F 07 07 07 7F 07
<EPA> 97 08 08 08 C2.97 08
<RI> 8D 09 09 09 C2.8D 09
<SS2> 8E 0A 0A 0A C2.8E 0A
<VT> 0B 0B 0B 0B 0B 0B
<FF> 0C 0C 0C 0C 0C 0C
<CR> 0D 0D 0D 0D 0D 0D
<SO> 0E 0E 0E 0E 0E 0E
<SI> 0F 0F 0F 0F 0F 0F
<DLE> 10 10 10 10 10 10
<DC1> 11 11 11 11 11 11
<DC2> 12 12 12 12 12 12
<DC3> 13 13 13 13 13 13
<OSC> 9D 14 14 14 C2.9D 14
<LF> 0A 25 15 15 0A 15 **
<BS> 08 16 16 16 08 16
<ESA> 87 17 17 17 C2.87 17
<CAN> 18 18 18 18 18 18
<EOM> 19 19 19 19 19 19
<PU2> 92 1A 1A 1A C2.92 1A
<SS3> 8F 1B 1B 1B C2.8F 1B
<FS> 1C 1C 1C 1C 1C 1C
<GS> 1D 1D 1D 1D 1D 1D
<RS> 1E 1E 1E 1E 1E 1E
<US> 1F 1F 1F 1F 1F 1F
<PAD> 80 20 20 20 C2.80 20
<HOP> 81 21 21 21 C2.81 21
<BPH> 82 22 22 22 C2.82 22
<NBH> 83 23 23 23 C2.83 23
<IND> 84 24 24 24 C2.84 24
<NEL> 85 15 25 25 C2.85 25 **
<ETB> 17 26 26 26 17 26
<ESC> 1B 27 27 27 1B 27
<HTS> 88 28 28 28 C2.88 28
<HTJ> 89 29 29 29 C2.89 29
<VTS> 8A 2A 2A 2A C2.8A 2A
<PLD> 8B 2B 2B 2B C2.8B 2B
<PLU> 8C 2C 2C 2C C2.8C 2C
<ENQ> 05 2D 2D 2D 05 2D
<ACK> 06 2E 2E 2E 06 2E
<BEL> 07 2F 2F 2F 07 2F
<DCS> 90 30 30 30 C2.90 30
<PU1> 91 31 31 31 C2.91 31
<SYN> 16 32 32 32 16 32
<STS> 93 33 33 33 C2.93 33
<CCH> 94 34 34 34 C2.94 34
<MW> 95 35 35 35 C2.95 35
<SPA> 96 36 36 36 C2.96 36
<EOT> 04 37 37 37 04 37
<SOS> 98 38 38 38 C2.98 38
<SGC> 99 39 39 39 C2.99 39
<SCI> 9A 3A 3A 3A C2.9A 3A
<CSI> 9B 3B 3B 3B C2.9B 3B
<DC4> 14 3C 3C 3C 14 3C
<NAK> 15 3D 3D 3D 15 3D
<PM> 9E 3E 3E 3E C2.9E 3E
<SUB> 1A 3F 3F 3F 1A 3F
<SPACE> 20 40 40 40 20 40
<NON-BREAKING SPACE> A0 41 41 41 C2.A0 80.41
<a WITH CIRCUMFLEX> E2 42 42 42 C3.A2 8B.43
<a WITH DIAERESIS> E4 43 43 43 C3.A4 8B.45
<a WITH GRAVE> E0 44 44 44 C3.A0 8B.41
<a WITH ACUTE> E1 45 45 45 C3.A1 8B.42
<a WITH TILDE> E3 46 46 46 C3.A3 8B.44
<a WITH RING ABOVE> E5 47 47 47 C3.A5 8B.46
<c WITH CEDILLA> E7 48 48 48 C3.A7 8B.48
<n WITH TILDE> F1 49 49 49 C3.B1 8B.58
<CENT SIGN> A2 4A 4A B0 C2.A2 80.43 ##
. 2E 4B 4B 4B 2E 4B
< 3C 4C 4C 4C 3C 4C
( 28 4D 4D 4D 28 4D
+ 2B 4E 4E 4E 2B 4E
| 7C 4F 4F 4F 7C 4F
& 26 50 50 50 26 50
<e WITH ACUTE> E9 51 51 51 C3.A9 8B.4A
<e WITH CIRCUMFLEX> EA 52 52 52 C3.AA 8B.51
<e WITH DIAERESIS> EB 53 53 53 C3.AB 8B.52
<e WITH GRAVE> E8 54 54 54 C3.A8 8B.49
<i WITH ACUTE> ED 55 55 55 C3.AD 8B.54
<i WITH CIRCUMFLEX> EE 56 56 56 C3.AE 8B.55
<i WITH DIAERESIS> EF 57 57 57 C3.AF 8B.56
<i WITH GRAVE> EC 58 58 58 C3.AC 8B.53
<SMALL LETTER SHARP S> DF 59 59 59 C3.9F 8A.73
! 21 5A 5A 5A 21 5A
$ 24 5B 5B 5B 24 5B
* 2A 5C 5C 5C 2A 5C
) 29 5D 5D 5D 29 5D
; 3B 5E 5E 5E 3B 5E
^ 5E B0 5F 6A 5E 5F ** ##
- 2D 60 60 60 2D 60
/ 2F 61 61 61 2F 61
<A WITH CIRCUMFLEX> C2 62 62 62 C3.82 8A.43
<A WITH DIAERESIS> C4 63 63 63 C3.84 8A.45
<A WITH GRAVE> C0 64 64 64 C3.80 8A.41
<A WITH ACUTE> C1 65 65 65 C3.81 8A.42
<A WITH TILDE> C3 66 66 66 C3.83 8A.44
<A WITH RING ABOVE> C5 67 67 67 C3.85 8A.46
<C WITH CEDILLA> C7 68 68 68 C3.87 8A.48
<N WITH TILDE> D1 69 69 69 C3.91 8A.58
<BROKEN BAR> A6 6A 6A D0 C2.A6 80.47 ##
, 2C 6B 6B 6B 2C 6B
% 25 6C 6C 6C 25 6C
_ 5F 6D 6D 6D 5F 6D
> 3E 6E 6E 6E 3E 6E
? 3F 6F 6F 6F 3F 6F
<o WITH STROKE> F8 70 70 70 C3.B8 8B.67
<E WITH ACUTE> C9 71 71 71 C3.89 8A.4A
<E WITH CIRCUMFLEX> CA 72 72 72 C3.8A 8A.51
<E WITH DIAERESIS> CB 73 73 73 C3.8B 8A.52
<E WITH GRAVE> C8 74 74 74 C3.88 8A.49
<I WITH ACUTE> CD 75 75 75 C3.8D 8A.54
<I WITH CIRCUMFLEX> CE 76 76 76 C3.8E 8A.55
<I WITH DIAERESIS> CF 77 77 77 C3.8F 8A.56
<I WITH GRAVE> CC 78 78 78 C3.8C 8A.53
` 60 79 79 4A 60 79 ##
: 3A 7A 7A 7A 3A 7A
# 23 7B 7B 7B 23 7B
@ 40 7C 7C 7C 40 7C
' 27 7D 7D 7D 27 7D
= 3D 7E 7E 7E 3D 7E
" 22 7F 7F 7F 22 7F
<O WITH STROKE> D8 80 80 80 C3.98 8A.67
a 61 81 81 81 61 81
b 62 82 82 82 62 82
c 63 83 83 83 63 83
d 64 84 84 84 64 84
e 65 85 85 85 65 85
f 66 86 86 86 66 86
g 67 87 87 87 67 87
h 68 88 88 88 68 88
i 69 89 89 89 69 89
<LEFT POINTING GUILLEMET> AB 8A 8A 8A C2.AB 80.52
<RIGHT POINTING GUILLEMET> BB 8B 8B 8B C2.BB 80.6A
<SMALL LETTER eth> F0 8C 8C 8C C3.B0 8B.57
<y WITH ACUTE> FD 8D 8D 8D C3.BD 8B.71
<SMALL LETTER thorn> FE 8E 8E 8E C3.BE 8B.72
<PLUS-OR-MINUS SIGN> B1 8F 8F 8F C2.B1 80.58
<DEGREE SIGN> B0 90 90 90 C2.B0 80.57
j 6A 91 91 91 6A 91
k 6B 92 92 92 6B 92
l 6C 93 93 93 6C 93
m 6D 94 94 94 6D 94
n 6E 95 95 95 6E 95
o 6F 96 96 96 6F 96
p 70 97 97 97 70 97
q 71 98 98 98 71 98
r 72 99 99 99 72 99
<FEMININE ORDINAL> AA 9A 9A 9A C2.AA 80.51
<MASC. ORDINAL INDICATOR> BA 9B 9B 9B C2.BA 80.69
<SMALL LIGATURE ae> E6 9C 9C 9C C3.A6 8B.47
<CEDILLA> B8 9D 9D 9D C2.B8 80.67
<CAPITAL LIGATURE AE> C6 9E 9E 9E C3.86 8A.47
<CURRENCY SIGN> A4 9F 9F 9F C2.A4 80.45
<MICRO SIGN> B5 A0 A0 A0 C2.B5 80.64
~ 7E A1 A1 FF 7E A1 ##
s 73 A2 A2 A2 73 A2
t 74 A3 A3 A3 74 A3
u 75 A4 A4 A4 75 A4
v 76 A5 A5 A5 76 A5
w 77 A6 A6 A6 77 A6
x 78 A7 A7 A7 78 A7
y 79 A8 A8 A8 79 A8
z 7A A9 A9 A9 7A A9
<INVERTED "!" > A1 AA AA AA C2.A1 80.42
<INVERTED QUESTION MARK> BF AB AB AB C2.BF 80.73
<CAPITAL LETTER ETH> D0 AC AC AC C3.90 8A.57
[ 5B BA AD BB 5B AD ** ##
<CAPITAL LETTER THORN> DE AE AE AE C3.9E 8A.72
<REGISTERED TRADE MARK> AE AF AF AF C2.AE 80.55
<NOT SIGN> AC 5F B0 BA C2.AC 80.53 ** ##
<POUND SIGN> A3 B1 B1 B1 C2.A3 80.44
<YEN SIGN> A5 B2 B2 B2 C2.A5 80.46
<MIDDLE DOT> B7 B3 B3 B3 C2.B7 80.66
<COPYRIGHT SIGN> A9 B4 B4 B4 C2.A9 80.4A
<SECTION SIGN> A7 B5 B5 B5 C2.A7 80.48
<PARAGRAPH SIGN> B6 B6 B6 B6 C2.B6 80.65
<FRACTION ONE QUARTER> BC B7 B7 B7 C2.BC 80.70
<FRACTION ONE HALF> BD B8 B8 B8 C2.BD 80.71
<FRACTION THREE QUARTERS> BE B9 B9 B9 C2.BE 80.72
<Y WITH ACUTE> DD AD BA AD C3.9D 8A.71 ** ##
<DIAERESIS> A8 BD BB 79 C2.A8 80.49 ** ##
<MACRON> AF BC BC A1 C2.AF 80.56 ##
] 5D BB BD BD 5D BD **
<ACUTE ACCENT> B4 BE BE BE C2.B4 80.63
<MULTIPLICATION SIGN> D7 BF BF BF C3.97 8A.66
{ 7B C0 C0 FB 7B C0 ##
A 41 C1 C1 C1 41 C1
B 42 C2 C2 C2 42 C2
C 43 C3 C3 C3 43 C3
D 44 C4 C4 C4 44 C4
E 45 C5 C5 C5 45 C5
F 46 C6 C6 C6 46 C6
G 47 C7 C7 C7 47 C7
H 48 C8 C8 C8 48 C8
I 49 C9 C9 C9 49 C9
<SOFT HYPHEN> AD CA CA CA C2.AD 80.54
<o WITH CIRCUMFLEX> F4 CB CB CB C3.B4 8B.63
<o WITH DIAERESIS> F6 CC CC CC C3.B6 8B.65
<o WITH GRAVE> F2 CD CD CD C3.B2 8B.59
<o WITH ACUTE> F3 CE CE CE C3.B3 8B.62
<o WITH TILDE> F5 CF CF CF C3.B5 8B.64
} 7D D0 D0 FD 7D D0 ##
J 4A D1 D1 D1 4A D1
K 4B D2 D2 D2 4B D2
L 4C D3 D3 D3 4C D3
M 4D D4 D4 D4 4D D4
N 4E D5 D5 D5 4E D5
O 4F D6 D6 D6 4F D6
P 50 D7 D7 D7 50 D7
Q 51 D8 D8 D8 51 D8
R 52 D9 D9 D9 52 D9
<SUPERSCRIPT ONE> B9 DA DA DA C2.B9 80.68
<u WITH CIRCUMFLEX> FB DB DB DB C3.BB 8B.6A
<u WITH DIAERESIS> FC DC DC DC C3.BC 8B.70
<u WITH GRAVE> F9 DD DD C0 C3.B9 8B.68 ##
<u WITH ACUTE> FA DE DE DE C3.BA 8B.69
<y WITH DIAERESIS> FF DF DF DF C3.BF 8B.73
\ 5C E0 E0 BC 5C E0 ##
<DIVISION SIGN> F7 E1 E1 E1 C3.B7 8B.66
S 53 E2 E2 E2 53 E2
T 54 E3 E3 E3 54 E3
U 55 E4 E4 E4 55 E4
V 56 E5 E5 E5 56 E5
W 57 E6 E6 E6 57 E6
X 58 E7 E7 E7 58 E7
Y 59 E8 E8 E8 59 E8
Z 5A E9 E9 E9 5A E9
<SUPERSCRIPT TWO> B2 EA EA EA C2.B2 80.59
<O WITH CIRCUMFLEX> D4 EB EB EB C3.94 8A.63
<O WITH DIAERESIS> D6 EC EC EC C3.96 8A.65
<O WITH GRAVE> D2 ED ED ED C3.92 8A.59
<O WITH ACUTE> D3 EE EE EE C3.93 8A.62
<O WITH TILDE> D5 EF EF EF C3.95 8A.64
0 30 F0 F0 F0 30 F0
1 31 F1 F1 F1 31 F1
2 32 F2 F2 F2 32 F2
3 33 F3 F3 F3 33 F3
4 34 F4 F4 F4 34 F4
5 35 F5 F5 F5 35 F5
6 36 F6 F6 F6 36 F6
7 37 F7 F7 F7 37 F7
8 38 F8 F8 F8 38 F8
9 39 F9 F9 F9 39 F9
<SUPERSCRIPT THREE> B3 FA FA FA C2.B3 80.62
<U WITH CIRCUMFLEX> DB FB FB DD C3.9B 8A.6A ##
<U WITH DIAERESIS> DC FC FC FC C3.9C 8A.70
<U WITH GRAVE> D9 FD FD E0 C3.99 8A.68 ##
<U WITH ACUTE> DA FE FE FE C3.9A 8A.69
<APC> 9F FF FF 5F C2.9F FF ##
可以判斷您正在使用哪一個字元集。但首先您需要非常非常確定您需要這麼做。如果您不需要測試字元集並執行不同的動作,您的程式碼會更簡單且可能更具可攜性。實際上,只有極少數的情況無法輕鬆撰寫可攜到所有字元集的直線程式碼。請參閱 perluniintro 中的「Unicode 和 EBCDIC」,了解如何以可攜方式指定字元。
但在某些情況下,您可能想知道您正在使用哪一個字元集。一個可能的範例是在效能至關重要的內部迴圈中執行 排序。
若要判斷您是否在 ASCII 或 EBCDIC 下執行,您可以使用 ord()
或 chr()
的傳回值來測試一個或多個字元值。例如
$is_ascii = "A" eq chr(65);
$is_ebcdic = "A" eq chr(193);
$is_ascii = ord("A") == 65;
$is_ebcdic = ord("A") == 193;
甚至更不需要區分 EBCDIC 編碼頁,但要這麼做,請嘗試查看它們之間不同的其中一個或多個字元。
$is_ascii = ord('[') == 91;
$is_ebcdic_37 = ord('[') == 186;
$is_ebcdic_1047 = ord('[') == 173;
$is_ebcdic_POSIX_BC = ord('[') == 187;
不過,撰寫類似這樣的測試是不明智的
$is_ascii = "\r" ne chr(13); # WRONG
$is_ascii = "\n" ne chr(10); # ILL ADVISED
顯然,第一個測試無法區分大多數 ASCII 平台與 CCSID 0037、1047 或 POSIX-BC EBCDIC 平台,因為 "\r" eq chr(13)
在所有這些編碼字元集中都是如此。但也要注意,因為 "\n"
是 chr(13)
,而 "\r"
是舊 Macintosh(一個 ASCII 平台)上的 chr(10)
,所以第二個 $is_ascii
測試將會導致問題。
若要判斷 perl 是否在 EBCDIC 編碼頁下建置,您可以使用 Config 模組,如下所示
use Config;
$is_ebcdic = $Config{'ebcdic'} eq 'define';
utf8::unicode_to_native()
和 utf8::native_to_unicode()
這些函式會在一個編碼中取得輸入數值碼點,並傳回其在另一個編碼中的等值。
請參閱 utf8。
若要將字元串從一個字元集轉換到另一個字元集,只需要一個數字清單,例如上表右欄中的清單,以及 Perl 的 tr///
算子。表格中的資料以 ASCII/Latin1 順序排列,因此 EBCDIC 欄提供易於使用的 ASCII/Latin1 轉 EBCDIC 作業,而且也容易反向執行。
例如,要將 ASCII/Latin1 轉換為編碼頁 037,請採用食譜 2 輸出中的第二個數字欄位的輸出(修改為加入 "\"
字元),並在 tr///
中使用,如下所示
$cp_037 =
'\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F' .
'\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F' .
'\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61' .
'\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F' .
'\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6' .
'\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xBA\xE0\xBB\xB0\x6D' .
'\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96' .
'\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07' .
'\x20\x21\x22\x23\x24\x15\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B' .
'\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF' .
'\x41\xAA\x4A\xB1\x9F\xB2\x6A\xB5\xBD\xB4\x9A\x8A\x5F\xCA\xAF\xBC' .
'\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB' .
'\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77' .
'\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59' .
'\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57' .
'\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF';
my $ebcdic_string = $ascii_string;
eval '$ebcdic_string =~ tr/\000-\377/' . $cp_037 . '/';
要從 EBCDIC 037 轉換為 ASCII,只需反轉 tr/// 參數的順序,如下所示
my $ascii_string = $ebcdic_string;
eval '$ascii_string =~ tr/' . $cp_037 . '/\000-\377/';
同樣地,可以採用食譜 2 中第三個數字欄位的輸出,以取得 $cp_1047
表格。食譜 2 輸出的第四個數字欄位可以提供一個適合轉碼的 $cp_posix_bc
表格。
如果您想查看反向表格,您必須先在食譜 4、5 或 6 中根據所需的數字欄位進行排序,然後採用第一個數字欄位的輸出。
XPG 可操作性通常表示存在一個可從 shell 或 C 函式庫取得的 iconv 實用程式。請參閱您的系統文件,以取得關於 iconv 的資訊。
在 OS/390 或 z/OS 上,請參閱 iconv(1) 手冊頁。從 perl 內部呼叫 iconv
shell 實用程式的一種方法是
# OS/390 or z/OS example
$ascii_data = `echo '$ebcdic_data'| iconv -f IBM-1047 -t ISO8859-1`
或反向對應
# OS/390 or z/OS example
$ebcdic_data = `echo '$ascii_data'| iconv -f ISO8859-1 -t IBM-1047`
對於其他基於 Perl 的轉換選項,請參閱 CPAN 上的 Convert::*
模組。
OS/390 和 z/OS C 執行時期函式庫提供 _atoe()
和 _etoa()
函式。
..
範圍運算子在 EBCDIC 平台上小心處理特定字元範圍。例如,下列陣列在 EBCDIC 平台或 ASCII 平台上將有二十六個元素
@alphabet = ('A'..'Z'); # $#alphabet == 25
當在 EBCDIC 平台上執行的 Perl 程式中對字串或字元資料進行運算時,位元運算子(例如 & ^ |)可能會傳回與在 ASCII 平台上執行時不同的結果。以下是從 perlop 中改編的範例
# EBCDIC-based examples
print "j p \n" ^ " a h"; # prints "JAPH\n"
print "JA" | " ph\n"; # prints "japh\n"
print "JAPH\nJunk" & "\277\277\277\277\277"; # prints "japh\n";
print 'p N$' ^ " E<H\n"; # prints "Perl\n";
ASCII 表中 32 個 C0 控制字元的有趣屬性是它們可以在 Perl 中「實際上」建構為控制字元,例如 (chr(0)
等於 \c@
)> (chr(1)
等於 \cA
)>,以此類推。EBCDIC 平台上的 Perl 已移植,可以將 \c@
轉換為 chr(0)
,將 \cA
轉換為 chr(1)
等,但產生的字元取決於您使用的代碼頁。下表使用控制字元的標準縮寫。POSIX-BC 和 1047 組在這個範圍內完全相同,只在一個位置(十進制 21)與 0037 組不同。請注意,行終止字元可以在 ASCII 平台上由 \cJ
產生,但在 1047 或 POSIX-BC 平台上由 \cU
產生,並且不能在 0037 平台上作為 "\c.letter."
控制字元產生。另請注意,\c\
不能是字串或正規表示式的最後一個元素,因為它會吸收終止符。但是 \c\X
是 FILE SEPARATOR
與 X 的串接,對於所有 X 皆成立。ASCII 上的異常值 \c?
會產生非 C0 控制字元 DEL
,在 EBCDIC 上會產生異常值控制字元 APC
,它不在連續控制字元的區塊中。請注意,這一點的微妙之處在於 ASCII 平台上的 \c?
是 ASCII 字元,而它不等於 EBCDIC 平台上的任何 ASCII 字元。
chr ord 8859-1 0037 1047 && POSIX-BC
-----------------------------------------------------------------------
\c@ 0 <NUL> <NUL> <NUL>
\cA 1 <SOH> <SOH> <SOH>
\cB 2 <STX> <STX> <STX>
\cC 3 <ETX> <ETX> <ETX>
\cD 4 <EOT> <ST> <ST>
\cE 5 <ENQ> <HT> <HT>
\cF 6 <ACK> <SSA> <SSA>
\cG 7 <BEL> <DEL> <DEL>
\cH 8 <BS> <EPA> <EPA>
\cI 9 <HT> <RI> <RI>
\cJ 10 <LF> <SS2> <SS2>
\cK 11 <VT> <VT> <VT>
\cL 12 <FF> <FF> <FF>
\cM 13 <CR> <CR> <CR>
\cN 14 <SO> <SO> <SO>
\cO 15 <SI> <SI> <SI>
\cP 16 <DLE> <DLE> <DLE>
\cQ 17 <DC1> <DC1> <DC1>
\cR 18 <DC2> <DC2> <DC2>
\cS 19 <DC3> <DC3> <DC3>
\cT 20 <DC4> <OSC> <OSC>
\cU 21 <NAK> <NEL> <LF> **
\cV 22 <SYN> <BS> <BS>
\cW 23 <ETB> <ESA> <ESA>
\cX 24 <CAN> <CAN> <CAN>
\cY 25 <EOM> <EOM> <EOM>
\cZ 26 <SUB> <PU2> <PU2>
\c[ 27 <ESC> <SS3> <SS3>
\c\X 28 <FS>X <FS>X <FS>X
\c] 29 <GS> <GS> <GS>
\c^ 30 <RS> <RS> <RS>
\c_ 31 <US> <US> <US>
\c? * <DEL> <APC> <APC>
*
注意:\c?
在 ASCII 平台上對應序號 127(DEL
),但由於序號 127 在 EBCDIC 電腦上不是控制字元,因此 \c?
在 EBCDIC 電腦上對應序號 255(0037 和 1047)或 95(POSIX-BC)的 APC
。
chr()
必須提供 chr()
一個 EBCDIC 碼數字引數,才能在 EBCDIC 平台上產生所需的字元傳回值。例如
$CAPITAL_LETTER_A = chr(193);
ord()
ord()
會在 EBCDIC 平台上傳回 EBCDIC 碼數字值。例如
$the_number_193 = ord("A");
pack()
pack()
的 "c"
和 "C"
範本取決於字元集編碼。EBCDIC 上的使用範例包括
$foo = pack("CCCC",193,194,195,196);
# $foo eq "ABCD"
$foo = pack("C4",193,194,195,196);
# same thing
$foo = pack("ccxxcc",193,194,195,196);
# $foo eq "AB\0\0CD"
"U"
範本已移植到所有平台上,表示「Unicode」,因此
pack("U", 65) eq 'A'
在所有平台上都成立。如果您想要低 256 的原生碼點,請使用 "W"
範本。這表示等價關係
pack("W", ord($character)) eq $character
unpack("W", $character) == ord $character
會成立。
print()
必須小心傳遞給 print 的純量和字串,其中包含 ASCII 編碼。發生這種情況的一個常見地方是在 CGI 程式寫作的 MIME 類型標頭輸出中。例如,許多 Perl 程式設計指南建議類似於
print "Content-type:\ttext/html\015\012\015\012";
# this may be wrong on EBCDIC
您可以改寫為
print "Content-type:\ttext/html\r\n\r\n"; # OK for DGW et al
並讓它可移植地工作。
這是因為從 EBCDIC 轉換為 ASCII 是由網路伺服器在此情況下完成的。請參閱網路伺服器的文件以取得進一步的詳細資訊。
printf()
在 EBCDIC 平台上執行時,可以將字元轉換為數字,反之亦然的格式將與其 ASCII 對應項不同。範例包括
printf("%c%c%c",193,194,195); # prints ABC
sort()
EBCDIC 排序結果可能與 ASCII 排序結果不同,特別是對於混合大小寫的字串。這在 下方有更詳細的討論。
sprintf()
請參閱上面 "printf()"
的討論。sprintf 使用範例如下
$CAPITAL_LETTER_A = sprintf("%c",193);
unpack()
請參閱上面 "pack()"
的討論。
請注意,透過指定 Unicode 數字和使用轉換函數,可以為這些函數撰寫可移植的程式碼
printf("%c",utf8::unicode_to_native(65)); # prints A on all
# platforms
print utf8::native_to_unicode(ord("A")); # Likewise, prints 65
請參閱 "perluniintro 中的 Unicode 和 EBCDIC" 和 "轉換" 以取得其他選項。
您可以像 ASCII 平台上的某人一樣撰寫正規表示式。但請記住,使用八進位或十六進位表示法來指定特定代碼點會提供 EBCDIC 代碼頁原生對應的字元。(這也適用於所有雙引號字串。)如果您想可移植地撰寫,請在您會使用 \x{...}
的任何地方使用 \N{U+...}
表示法,並且完全不要使用八進位表示法。
從 Perl v5.22 開始,這適用於括號字元類別中的範圍。例如,如果您說 qr/[\N{U+20}-\N{U+7F}]/
,它表示字元 \N{U+20}
、\N{U+21}
、...、\N{U+7F}
。此範圍是 ASCII 字元集包含的所有可列印字元。
在 v5.22 之前,您無法可移植地指定任何範圍,除了 (從 Perl v5.5.3 開始) [A-Z]
和 [a-z]
範圍的所有子集都被特別編碼為不選取間隙字元。例如,介於 "I" 和 "J" 之間的字元,例如 "ô" (帶圓音符號的 o
) 將不會與正規表示式範圍 /[H-K]/
相符。但是,如果範圍端點之一明確為數字 (且兩者都沒有由 \N{U+...}
指定),則會比對間隙字元
/[\x89-\x91]/
將比對 \x8e
,即使 \x89
是 "i",\x91
是 "j",而 \x8e
從字母觀點來看是間隙字元。
另一個要注意的建構是十六進位 (除非您使用 \N{U+...}
) 或八進位常數在正規表示式中不當使用。考慮下列子集
sub is_c0 {
my $char = substr(shift,0,1);
$char =~ /[\000-\037]/;
}
sub is_print_ascii {
my $char = substr(shift,0,1);
$char =~ /[\040-\176]/;
}
sub is_delete {
my $char = substr(shift,0,1);
$char eq "\177";
}
sub is_c1 {
my $char = substr(shift,0,1);
$char =~ /[\200-\237]/;
}
sub is_latin_1 { # But not ASCII; not C1
my $char = substr(shift,0,1);
$char =~ /[\240-\377]/;
}
這些僅在 ASCII 平台上有效。從 Perl v5.22 開始,只需將八進位常數變更為等效的 \N{U+...}
值即可攜帶
sub is_c0 {
my $char = substr(shift,0,1);
$char =~ /[\N{U+00}-\N{U+1F}]/;
}
sub is_print_ascii {
my $char = substr(shift,0,1);
$char =~ /[\N{U+20}-\N{U+7E}]/;
}
sub is_delete {
my $char = substr(shift,0,1);
$char eq "\N{U+7F}";
}
sub is_c1 {
my $char = substr(shift,0,1);
$char =~ /[\N{U+80}-\N{U+9F}]/;
}
sub is_latin_1 { # But not ASCII; not C1
my $char = substr(shift,0,1);
$char =~ /[\N{U+A0}-\N{U+FF}]/;
}
以下是撰寫它們的一些替代攜帶方式
sub Is_c0 {
my $char = substr(shift,0,1);
return $char =~ /[[:cntrl:]]/a && ! Is_delete($char);
# Alternatively:
# return $char =~ /[[:cntrl:]]/
# && $char =~ /[[:ascii:]]/
# && ! Is_delete($char);
}
sub Is_print_ascii {
my $char = substr(shift,0,1);
return $char =~ /[[:print:]]/a;
# Alternatively:
# return $char =~ /[[:print:]]/ && $char =~ /[[:ascii:]]/;
# Or
# return $char
# =~ /[ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~]/;
}
sub Is_delete {
my $char = substr(shift,0,1);
return utf8::native_to_unicode(ord $char) == 0x7F;
}
sub Is_c1 {
use feature 'unicode_strings';
my $char = substr(shift,0,1);
return $char =~ /[[:cntrl:]]/ && $char !~ /[[:ascii:]]/;
}
sub Is_latin_1 { # But not ASCII; not C1
use feature 'unicode_strings';
my $char = substr(shift,0,1);
return ord($char) < 256
&& $char !~ /[[:ascii:]]/
&& $char !~ /[[:cntrl:]]/;
}
撰寫 Is_latin_1()
的另一種方式是明確使用範圍內的字元
sub Is_latin_1 {
my $char = substr(shift,0,1);
$char =~ /[ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ]
[ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ]/x;
}
儘管該表單可能會在網路傳輸中遇到問題 (由於 8 位元字元的出現) 或在非 ISO-Latin 字元集上。但它確實允許 Is_c1
重新撰寫,以便在沒有 'unicode_strings'
(早於 v5.14) 的 Perl 上執行
sub Is_latin_1 { # But not ASCII; not C1
my $char = substr(shift,0,1);
return ord($char) < 256
&& $char !~ /[[:ascii:]]/
&& ! Is_latin1($char);
}
大多數 socket 程式設計假設網路位元組順序中的 ASCII 字元編碼。例外情況包括在主機網路伺服器下撰寫 CGI 腳本,其中伺服器可能會為您處理轉換。大多數主機網路伺服器會在輸出時將 EBCDIC 資料轉換為 ISO-8859-1 或 Unicode。
基於 ASCII 的字元集和 EBCDIC 字元集之間的一個重大差異是在原生順序中排序時字元的相對位置。最令人關注的是大小寫字母、數字和底線 ("_"
)。在 ASCII 平台上,原生排序順序是數字出現在大寫字母之前,大寫字母出現在底線之前,底線出現在小寫字母之前。在 EBCDIC 上,底線優先,然後是小寫字母,然後是大寫字母,最後是數字。如果在基於 ASCII 的平台上排序,則醫師的兩個字母縮寫會出現在驅動器的兩個字母縮寫之前;也就是說
@sorted = sort(qw(Dr. dr.)); # @sorted holds ('Dr.','dr.') on ASCII,
# but ('dr.','Dr.') on EBCDIC
EBCDIC 中小寫字母在大寫字母之前的特性甚至會傳遞到拉丁文 1 EBCDIC 頁面,例如 0037 和 1047。一個例子是 "Ë" (E WITH DIAERESIS
,203) 出現在 "ë" (e WITH DIAERESIS
,235) 之前在 ASCII 平台上,但後者 (83) 出現在前者 (115) 之前在 EBCDIC 平台上。(精明的讀者會注意到 "ß" SMALL LETTER SHARP S
的大寫版本只是 "SS",而 "ÿ" (小寫 y WITH DIAERESIS
) 和 "µ" (MICRO SIGN
) 的大寫版本不在 0..255 範圍內,但在 Unicode 中,在啟用 Unicode 的 Perl 中)。
排序順序會造成在 ASCII 平台上取得的結果與在 EBCDIC 平台上取得的結果之間的差異。以下是一些處理這些差異的建議。
這是運算成本最低的策略。它可能需要一些使用者教育。
這是完全通用的,但運算成本最高的策略。選擇一個字元集並在每次排序比較時轉換為該字元集。以下是轉換為 ASCII 排序順序的完整範例
sub native_to_uni($) {
my $string = shift;
# Saves time on an ASCII platform
return $string if ord 'A' == 65;
my $output = "";
for my $i (0 .. length($string) - 1) {
$output
.= chr(utf8::native_to_unicode(ord(substr($string, $i, 1))));
}
# Preserve utf8ness of input onto the output, even if it didn't need
# to be utf8
utf8::upgrade($output) if utf8::is_utf8($string);
return $output;
}
sub ascii_order { # Sort helper
return native_to_uni($a) cmp native_to_uni($b);
}
sort ascii_order @list;
如果您不在乎數字和底線的排序位置,您可以執行類似這樣的操作
sub case_insensitive_order { # Sort helper
return lc($a) cmp lc($b)
}
sort case_insensitive_order @list;
如果效能是一個問題,而且您不在乎輸出是否與輸入大小寫相同,請使用 tr///
轉換為資料中最常用的大小寫。如果資料主要是非拉丁碼 1 的大寫,則套用 tr/[a-z]/[A-Z]/
,然後 sort()
。如果資料主要是非拉丁碼 1 的小寫,則在排序之前套用 tr/[A-Z]/[a-z]/
。如果資料主要是大寫並包含拉丁碼 1 字元,則套用
tr/[a-z]/[A-Z]/;
tr/[àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ]/[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ/;
s/ß/SS/g;
然後 sort()
。如果您有選擇,最好將所有內容轉換為小寫,以避免兩個拉丁碼 1 字元的大寫在拉丁碼 1 之外造成的問題:「ÿ」(小寫 帶分音符號的 y
)和「µ」(微小符號
)。如果您確實需要轉換為大寫,您可以使用啟用 Unicode 的 Perl 執行
tr/ÿ/\x{178}/;
tr/µ/\x{39C}/;
此策略可以使用網路連線。因此,它的運算成本會很高。
有許多方法可以用於轉換資料,這些方法使用字元集內對應,並服務於各種目的。排序已在上一節中討論,接下來將討論一些其他更流行的對應技術。
請注意,一些 URL 中包含十六進位 ASCII 碼點,以嘗試克服字元或協定限制問題。例如,並非每個鍵盤都有波浪號字元,因此形式為
http://www.pvhp.com/~pvhp/
也可以表示為
http://www.pvhp.com/%7Epvhp/
http://www.pvhp.com/%7epvhp/
其中 7E 是 "~" 的十六進位 ASCII 碼點。以下是使用任何 EBCDIC 碼頁解碼此類 URL 的範例
$url = 'http://www.pvhp.com/%7Epvhp/';
$url =~ s/%([0-9a-fA-F]{2})/
pack("c",utf8::unicode_to_native(hex($1)))/xge;
相反地,以下是使用任何 EBCDIC 碼頁對此類 URL 進行編碼任務的部分解決方案
$url = 'http://www.pvhp.com/~pvhp/';
# The following regular expression does not address the
# mappings for: ('.' => '%2E', '/' => '%2F', ':' => '%3A')
$url =~ s/([\t "#%&\(\),;<=>\?\@\[\\\]^`{|}~])/
sprintf("%%%02X",utf8::native_to_unicode(ord($1)))/xge;
更完整的解決方案會將 URL 分割成組成部分,並僅對適當的部分套用完整的 s/// 替換。
u
範本用於 pack()
或 unpack()
會以等同於其 ASCII 對應字元的 EBCDIC 字元呈現 EBCDIC 資料。例如,下列程式碼會在 ASCII 或 EBCDIC 電腦上列印「Yes indeed\n」
$all_byte_chrs = '';
for (0..255) { $all_byte_chrs .= chr($_); }
$uuencode_byte_chrs = pack('u', $all_byte_chrs);
($uu = <<'ENDOFHEREDOC') =~ s/^\s*//gm;
M``$"`P0%!@<("0H+#`T.#Q`1$A,4%187&!D:&QP='A\@(2(C)"4F)R@I*BLL
M+2XO,#$R,S0U-C<X.3H[/#T^/T!!0D-$149'2$E*2TQ-3D]045)35%565UA9
M6EM<75Y?8&%B8V1E9F=H:6IK;&UN;W!Q<G-T=79W>'EZ>WQ]?G^`@8*#A(6&
MAXB)BHN,C8Z/D)&2DY25EI>8F9J;G)V>GZ"AHJ.DI::GJ*FJJZRMKJ^PL;*S
MM+6VM[BYNKN\O;Z_P,'"P\3%QL?(R<K+S,W.S]#1TM/4U=;7V-G:V]S=WM_@
?X>+CY.7FY^CIZNOL[>[O\/'R\_3U]O?X^?K[_/W^_P``
ENDOFHEREDOC
if ($uuencode_byte_chrs eq $uu) {
print "Yes ";
}
$uudecode_byte_chrs = unpack('u', $uuencode_byte_chrs);
if ($uudecode_byte_chrs eq $all_byte_chrs) {
print "indeed\n";
}
以下是可以在 EBCDIC 上運作的極簡 uudecoder
#!/usr/local/bin/perl
$_ = <> until ($mode,$file) = /^begin\s*(\d*)\s*(\S*)/;
open(OUT, "> $file") if $file ne "";
while(<>) {
last if /^end/;
next if /[a-z]/;
next unless int((((utf8::native_to_unicode(ord()) - 32 ) & 077)
+ 2) / 3)
== int(length() / 4);
print OUT unpack("u", $_);
}
close(OUT);
chmod oct($mode), $file;
在 ASCII 編碼的平台上,可以使用下列方式移除可列印集外的字元
# This QP encoder works on ASCII only
$qp_string =~ s/([=\x00-\x1F\x80-\xFF])/
sprintf("=%02X",ord($1))/xge;
從 Perl v5.22 開始,這可以輕易地變更,以便在 ASCII 和 EBCDIC 平台上可攜式運作。
# This QP encoder works on both ASCII and EBCDIC
$qp_string =~ s/([=\N{U+00}-\N{U+1F}\N{U+80}-\N{U+FF}])/
sprintf("=%02X",ord($1))/xge;
對於較早的 Perl,可以在 ASCII 和 EBCDIC 平台上運作的 QP 編碼器會類似下列程式碼
$delete = utf8::unicode_to_native(ord("\x7F"));
$qp_string =~
s/([^[:print:]$delete])/
sprintf("=%02X",utf8::native_to_unicode(ord($1)))/xage;
(儘管在實際程式碼中,替換可能會在 EBCDIC 分支中使用函式呼叫進行,並在 ASCII 分支中單獨進行,而不會產生身分對應的開銷;在 Perl v5.22 中,身分對應會進行最佳化,因此不會產生開銷,但上述替代方案較為簡單,而且在 v5.22 中也可用)。
此類 QP 字串可以使用下列方式解碼
# This QP decoder is limited to ASCII only
$string =~ s/=([[:xdigit:][[:xdigit:])/chr hex $1/ge;
$string =~ s/=[\n\r]+$//;
可以在 ASCII 和 EBCDIC 平台上運作的 QP 解碼器會類似下列程式碼
$string =~ s/=([[:xdigit:][:xdigit:]])/
chr utf8::native_to_unicode(hex $1)/xge;
$string =~ s/=[\n\r]+$//;
將字母表向後或向前移動一個或多個字元以進行加密的做法可以追溯到數千年前,而且蓋尤斯·尤利烏斯·凱撒在他的高盧戰記中明確地詳細說明了這種做法。單一字母表移動有時稱為旋轉,而移動量會在字串「rot」或「rot$n」後以數字 $n 表示。Rot0 和 rot26 會在拉丁字母表的 26 個字母英文版本上指定身分對應。Rot13 具有有趣的特性,即交替後續呼叫會是身分對應(因此 rot13 是其在 26 個字母旋轉群組中非平凡的逆運算)。因此,以下是可以在 ASCII 和 EBCDIC 平台上運作的 rot13 編碼器和解碼器
#!/usr/local/bin/perl
while(<>){
tr/n-za-mN-ZA-M/a-zA-Z/;
print;
}
單行形式
perl -ne 'tr/n-za-mN-ZA-M/a-zA-Z/;print'
Perl 故意將雜湊順序隨機化,以確保 ASCII 和 EBCDIC 平台上的安全性。
將同一檔案轉換為 ASCII 和 EBCDIC 後,其校驗和將有所不同,反之亦然。
國際化 (I18N) 和在地化 (L10N) 至少在原則上受支援,即使是在 EBCDIC 平台上。詳細資訊取決於系統,並在下列 「作業系統問題」 區段中討論。
Perl 使用 UTF-EBCDIC,這是一種多位元組編碼。在早於 v5.22 的 Perl 版本中,可能會出現各種相關錯誤。
舊版多位元組 EBCDIC 程式碼頁 XXX。
對於 EBCDIC Perl 程式設計人員來說,可能會有一些系統相關問題需要關注。
PASE 環境是 OS/400 的執行時期環境,可以在 OS/400 中執行為 PowerPC AIX 建置的可執行檔;請參閱 perlos400。PASE 是以 ASCII 為基礎,而不是像 ILE 一樣以 EBCDIC 為基礎。
XXX。
Perl 在 Unix Systems Services 或 USS 下執行。
sigaction
SA_SIGINFO
可能會產生分段錯誤。
chcp
chcp 受支援作為一個 shell 工具程式,用於顯示和變更自己的程式碼頁。另請參閱 chcp(1)。
對於順序資料集存取,請嘗試
my @ds_records = `cat //DSNAME`;
或
my @ds_records = `cat //'HLQ.DSNAME'`;
另請參閱 CPAN 上的 OS390::Stdio 模組。
iconv
iconv 受支援作為 shell 工具程式和 C RTL 常式。另請參閱 iconv(1) 和 iconv(3) 手冊頁面。
支援區域設定。當區域設定是另一個 EBCDIC 編碼頁面時,可能會發生故障,因為其他位置有一些 編碼頁面變體字元。
目前沒有任何真正的 UTF-8 區域設定,即使有些區域設定名稱包含字串「UTF-8」。
請參閱 perllocale 以取得有關區域設定的資訊。L10N 檔案位於 /usr/nls/locale 中。$Config{d_setlocale}
在 OS/390 或 z/OS 上為 'define'
。
XXX。
並非所有 shell 都允許將多個 perl -e
字串引數正確串聯在一起,就像本文件中的範例 0、2、4、5 和 6 所暗示的那樣。
Perl v5.22 和 5.24 附帶的 CPAN 模組中有大量的測試失敗。這些僅出現在並非主要由 Perl 5 維護者維護的模組中。其中一些僅是測試失敗:它們沒有意識到在 EBCDIC 平台上取得不同的結果是正確的。而有些失敗則是真正的錯誤。如果您編譯 Perl 並執行 make test
,則會略過 /cpan
目錄中的所有測試。
Encode 部分運作。
在較早的 Perl 版本中,當位元組和字元資料串聯在一起時,有時會透過將位元組字串解碼為 ISO 8859-1 (Latin-1) 來建立新的字串,即使舊的 Unicode 字串使用 EBCDIC。
perllocale、perlfunc、perlunicode、utf8。
http://std.dkuug.dk/i18n/charmaps
https://www.unicode.org/reports/tr16/
https://www.sr-ix.com/Archive/CharCodeHist/index.html ASCII:資訊滲透的美國標準代碼 湯姆·詹寧斯,1999 年 9 月。
Unicode 標準,版本 3.0 Unicode 聯盟,莉莎·摩爾編輯,ISBN 0-201-61633-5,艾迪生·韋斯利開發人員出版社,2000 年 2 月。
CDRA:IBM - 字元資料表示架構 - 參考和註冊,IBM SC09-2190-00,1996 年 12 月。
「揭開字元集的神秘面紗」,安德莉亞·文恩,多語言運算與技術,#26 第 10 卷第 4 期,1999 年 8 月/9 月;ISSN 1523-0309;多語言運算公司,美國愛達荷州桑德波因特。
代碼、密碼和其他隱密和秘密通訊 弗雷德·B·賴克森,ISBN 1-57912-040-7,黑狗與李文索出版社,1998 年。
http://www.bobbemer.com/P-BIT.HTM IBM - EBCDIC 和 P-bit;史上最大的電腦錯誤 羅伯特·貝默。
2001 年 4 月 15 日:將 UTF-8 和 UTF-EBCDIC 加入主表,pvhp。
Peter Prymmer pvhp@best.com 於 1999 年和 2000 年撰寫本文,並得到 Chris Leach 和 André Pirard A.Pirard@ulg.ac.be 提供的 CCSID 0819 和 0037 協助,以及 Thomas Dorner Thomas.Dorner@start.de 提供的 POSIX-BC 協助。也要感謝 Vickie Cooper、Philip Newton、William Raffloer 和 Joe Smith。本文中使用的商標、註冊商標、服務標誌和註冊服務標誌為其各自所有者的財產。
目前由 Perl5 Porters 維護。