内容

名称

perlebcdic - 在 EBCDIC 平台上运行 Perl 的注意事项

描述

探讨了 EBCDIC 基于计算机的 Perl 程序员面临的一些问题。

本文档中仍未完成的部分用 XXX 标记。

早期的 Perl 版本在一些 EBCDIC 机器上运行,但最后一个在 EBCDIC 上运行的已知版本是 v5.8.7,直到 v5.22,Perl 核心才再次在 z/OS 上运行。理论上,它可以在 OS/400 或西门子的 BS2000(或其后续版本)上运行,但这尚未经过测试。在 v5.22 和 5.24 中,并非所有在 CPAN 上找到但与 Perl 核心一起提供的模块都可以在 z/OS 上运行。

如果您想在非 z/OS EBCDIC 机器上使用 Perl,请在 https://github.com/Perl/perl5/issues 上告知我们。

在 EBCDIC 平台上编写 Perl 与在 "ASCII" 平台上编写并没有什么不同,只是底层数字不同,我们很快就会看到。您需要了解一些关于 "ASCII" 平台的信息,因为文档存在偏差,并且经常使用不适用于 EBCDIC 的示例数字。此外,很少有为 EBCDIC 编写的 CPAN 模块,这些模块在 ASCII 上无法运行;相反,绝大多数 CPAN 模块都是为 ASCII 编写的,有些可能恰好在 EBCDIC 上运行,而有些则被设计为可移植地在两者上运行。

如果您的代码只使用 52 个字母 A-Z 和 a-z,加上空格、数字 0-9 和 Perl 使用的标点符号,以及一些由转义序列表示的控制字符,例如 \n\t,那么使用 Perl 就没有特殊之处,您的代码很可能在 ASCII 机器上无需更改即可运行。

但是,如果您编写的代码使用\005表示制表符,或使用\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

美国信息交换标准代码(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 的任何内容。因此,这些是单字节(或者如果你愿意,可以称为八位字节)字符集。其中一个重要的字符集是 ISO 8859-1 字符集(因为 Unicode 是它的超集)。

ISO 8859

ISO 8859-$n 是国际标准化组织 (ISO) 的一系列字符代码集,每个代码集都向 ASCII 集添加了通常在各种语言中发现的字符,其中许多语言基于罗马字母或拉丁字母。大多数代码集用于欧洲语言,但也有一些代码集用于阿拉伯语、希腊语、希伯来语和泰语。网上有很多关于这些代码集的参考资料。

拉丁 1 (ISO 8859-1)

ASCII 的一个特殊的 8 位扩展,包括重音和锐音拉丁字符。可以使用 ISO 8859-1 的语言包括所有由 ASCII 涵盖的语言,以及南非荷兰语、阿尔巴尼亚语、巴斯克语、加泰罗尼亚语、丹麦语、法罗语、芬兰语、挪威语、葡萄牙语、西班牙语和瑞典语。荷兰语也涵盖在内,尽管没有 ij 连字。法语也涵盖在内,但没有 oe 连字。德语可以使用 ISO 8859-1,但必须不使用德式引号。此字符集基于 ASCII 的西欧扩展,在万维网工作中经常遇到。在 IBM 字符代码集识别术语中,ISO 8859-1 也称为 CCSID 819(有时也称为 0819 或 00819)。

EBCDIC

扩展二进制编码十进制交换码指的是一大批单字节和多字节编码字符集,它们与 ASCII 和 ISO 8859-1 非常不同,并且彼此之间也略有不同;它们通常运行在主机计算机上。EBCDIC 编码源于霍勒瑞斯穿孔卡片编码的 8 位字节扩展,这些编码早于 ASCII 出现。卡片上的布局使得高位被设置为大小写字母 [a-z][A-Z],但在每个拉丁字母范围内都有间隙,在 下面的 表格中可以看到。这些间隙会导致复杂情况。

一些 IBM EBCDIC 字符集可能以字符代码集识别号(CCSID 号)或代码页号来识别。

Perl 可以编译在运行以下三种常用 EBCDIC 字符集的平台上。

13 个变体字符

在 IBM EBCDIC 字符代码集中,有 13 个字符通常映射到不同的整数值。这些字符被称为 13 个“变体”字符,它们是

\ [ ] { } ^ ~ ! # | $ @ `

当 Perl 为某个平台编译时,它会查看所有这些字符,以猜测该平台使用哪个 EBCDIC 字符集,并相应地调整自身以适应该平台。如果该平台使用的字符集不是 Perl 知道的三个字符集之一,Perl 可能会编译失败,或者错误地且静默地选择其中一个。

换行符 (LF) 实际上是第 14 个变体字符,Perl 也会检查它。

Perl 识别的 EBCDIC 代码集

0037

字符代码集 ID 0037 是 ASCII 加 Latin-1 字符(即 ISO 8859-1)到 EBCDIC 集的映射。0037 用于运行在 AS/400 计算机上的 OS/400 操作系统的北美英语语言环境中。CCSID 0037 在 236 个地方与 ISO 8859-1 不同;换句话说,它们只在 20 个代码点值上达成一致。

1047

字符代码集 ID 1047 也是 ASCII 加 Latin-1 字符(即 ISO 8859-1)到 EBCDIC 集的映射。1047 用于 OS/390 或 z/OS 的 Unix 系统服务以及 VM/ESA 的 OpenEdition。CCSID 1047 在八个地方与 CCSID 0037 不同,在 236 个地方与 ISO 8859-1 不同。

POSIX-BC

西门子 BS2000 系统上使用的 EBCDIC 代码页与 1047 和 0037 不同。它在下面被标识为 POSIX-BC 集。与 0037 和 1047 一样,它在 20 个代码点值上与 ISO 8859-1 相同。

Unicode 代码点与 EBCDIC 代码点

在 Unicode 术语中,代码点是指分配给字符的数字:例如,在 EBCDIC 中,字符“A”通常分配数字 193。在 Unicode 中,字符“A”分配数字 65。ASCII 和 Latin-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 控制(由八个 1 位组成 = 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 也这样做;您可以在下面的代码表中看到。这使得事情通常“正常工作”,您甚至不必意识到存在交换。

Unicode 和 UTF

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-EBCDIC”时只说“UTF-8”。在本文档的其余部分,我们也大多会非正式地使用它。)在 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 的代码点,但对于更大的代码点使用不兼容的方法,以使其能够处理比其他方法更大的代码点。

使用 Encode

从 Perl 5.8 开始,您可以使用标准模块 Encode 将 EBCDIC 转换为 Latin-1 代码点。Encode 了解比 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

对于 I/O 操作,建议您使用 PerlIO 的自动转换功能,请参阅 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";

获取四个文件,它们分别包含 ASCII、CP 0037 EBCDIC、ISO 8859-1 (Latin-1)(在本例中与 ASCII 相同,因为只打印了 ASCII 字符)和 UTF-EBCDIC(在本例中与普通 EBCDIC 相同,因为只打印了 EBCDIC 和 UTF-EBCDIC 之间没有区别的字符)中的 "Hello World!\n"。有关详细信息,请参阅 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)。在表格中,Latin 1 对 ASCII 的扩展名称已使用大致对应于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 转换)通过

配方 0
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 代码点,那么在脚本形式中,您可能需要编写

配方 1
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);
        }
    }
}

如果您想查看此表格的十六进制值列表,请运行表格通过

配方 2
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 代码点

配方 3
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 顺序,请运行表格通过

配方 4
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,如下所示

配方 5
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,如下所示

配方 6
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 顺序排序

自从本文档首次编写以来,使用十六进制表示法来表示代码点的约定越来越普遍。要使用此方法来处理这些配方并进行排序,需要一个多步骤的过程,因此,为了方便起见,这里提供了上面表格的重新排序版本,按代码页 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)。但也要注意,因为在旧的 Macintosh(这是一个 ASCII 平台)上,"\n"chr(13),而 "\r"chr(10),所以第二个 $is_ascii 测试在那里会导致问题。

要确定 perl 是否在 EBCDIC 代码页下构建,您可以使用 Config 模块,如下所示

use Config;
$is_ebcdic = $Config{'ebcdic'} eq 'define';

转换

utf8::unicode_to_native()utf8::native_to_unicode()

这些函数接受一种编码中的输入数字代码点,并返回其在另一种编码中的等效值。

请参见 utf8

tr///

为了将字符串从一种字符集转换为另一种字符集,只需要一个简单的数字列表(如上表右列所示)以及 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 中的所需数字列进行排序,然后获取第一列数字的输出。

iconv

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::* 模块。

C RTL

OS/390 和 z/OS C 运行时库提供 _atoe()_etoa() 函数。

运算符差异

.. 范围运算符在 EBCDIC 平台上会谨慎地处理某些字符范围。例如,以下数组在 EBCDIC 平台或 ASCII 平台上都将有 26 个元素

@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) eq \c@)> (chr(1) eq \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 SEPARATORX 的连接,对于所有 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? 在它们上映射到 APC,在 0037 和 1047 中是 255,在 POSIX-BC 中是 95。

功能差异

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 的转换是由 Web 服务器完成的。有关更多详细信息,请参阅您的 Web 服务器文档。

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""CONVERSIONS" 以获取其他选项。

正则表达式差异

您可以像在 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] 范围的所有子集都被专门编码为不拾取间隙字符。例如,诸如 "ô"(o WITH CIRCUMFLEX)之类的字符位于 "I" 和 "J" 之间,不会被正则表达式范围/[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' 的 Perl(早于 v5.14)上工作

sub Is_latin_1 {    # But not ASCII; not C1
    my $char = substr(shift,0,1);
    return ord($char) < 256
           && $char !~ /[[:ascii:]]/
           && ! Is_latin1($char);
}

套接字

大多数套接字编程假设网络字节序中的 ASCII 字符编码。例外情况包括在主机 Web 服务器下编写 CGI 脚本,其中服务器可能会为您处理转换。大多数主机 Web 服务器将 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 中小写字母排序顺序的特性甚至延续到了 Latin 1 EBCDIC 页面,例如 0037 和 1047。例如,在 ASCII 平台上,"Ë" (E WITH DIAERESIS, 203) 排在 "ë" (e WITH DIAERESIS, 235) 之前,但在 EBCDIC 平台上,后者 (83) 排在前者 (115) 之前。(敏锐的读者会注意到,"ß" (SMALL LETTER SHARP S) 的大写形式只是 "SS",而 "ÿ" (小写 y WITH DIAERESIS) 和 "µ" (MICRO SIGN) 的大写形式不在 0..255 范围内,而是在 Unicode 中,在一个支持 Unicode 的 Perl 中)。

排序顺序会导致在 ASCII 平台和 EBCDIC 平台上获得的结果之间存在差异。以下是一些关于如何处理这些差异的建议。

忽略 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/// 将数据转换为数据中使用最多的那个大小写。如果数据主要是大写非 Latin-1 字符,则应用 tr/[a-z]/[A-Z]/,然后 sort()。如果数据主要是小写非 Latin-1 字符,则在排序之前应用 tr/[A-Z]/[a-z]/。如果数据主要是大写并包含 Latin-1 字符,则应用

tr/[a-z]/[A-Z]/;
tr/[àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ]/[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ/;
s/ß/SS/g;

然后 sort()。如果您有选择,最好将数据转换为小写,以避免两个 Latin-1 字符的大写形式不在 Latin-1 范围内的麻烦:"ÿ" (小写 y WITH DIAERESIS) 和 "µ" (MICRO SIGN)。如果您确实需要将数据转换为大写,您可以这样做;在支持 Unicode 的 Perl 中,您可以执行

tr/ÿ/\x{178}/;
tr/µ/\x{39C}/;

仅在一个类型的平台上执行排序。

此策略可以使用网络连接。因此,它将是计算成本很高的。

转换格式

有多种方法可以使用字符集内部映射来转换数据,这些方法服务于各种目的。排序在上一节中进行了讨论,接下来将讨论一些其他更流行的映射技术。

URL 解码和编码

请注意,一些 URL 中包含十六进制 ASCII 码点,以解决字符或协议限制问题。例如,波浪号 (~) 不在所有键盘上,因此以下形式的 URL

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/// 替换。

uu 编码和解码

u 模板用于 pack()unpack() 将 EBCDIC 数据呈现为与其 ASCII 对应物等效的 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";
}

以下是一个非常简陋的 uudecoder,它将在 EBCDIC 上运行

#!/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;

Quoted-Printable 编码和解码

在 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 个字母旋转组中是它自己的非平凡逆)。因此,以下代码是 rot13 编码器和解码器,它将在 ASCII 和 EBCDIC 平台上运行

#!/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 后,EBCDIC 校验和将不同。

国际化和本地化

即使在 EBCDIC 平台上,国际化 (I18N) 和本地化 (L10N) 也至少在原则上得到支持。具体细节取决于系统,并在下面的 "操作系统问题" 部分讨论。

多字节字符集

Perl 使用 UTF-EBCDIC,一种多字节编码。在 v5.22 之前的 Perl 版本中,这方面可能存在各种错误。

旧版多字节 EBCDIC 代码页 XXX。

操作系统问题

EBCDIC Perl 程序员可能需要关注一些系统相关问题。

OS/400

PASE

PASE 环境是 OS/400 的运行时环境,可以在 OS/400 中运行为 PowerPC AIX 构建的可执行文件;请参阅 perlos400。PASE 基于 ASCII,而不是像 ILE 那样基于 EBCDIC。

IFS 访问

XXX。

OS/390, z/OS

Perl 在 Unix 系统服务 (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'

POSIX-BC?

XXX。

错误

另请参阅

perllocaleperlfuncperlunicodeutf8

参考资料

http://std.dkuug.dk/i18n/charmaps

https://www.unicode.org/

https://www.unicode.org/reports/tr16/

https://www.sr-ix.com/Archive/CharCodeHist/index.html ASCII:美国信息交换标准代码 Tom Jennings,1999 年 9 月。

Unicode 标准,版本 3.0 Unicode 联盟,Lisa Moore 编,ISBN 0-201-61633-5,Addison Wesley 开发者出版社,2000 年 2 月。

CDRA:IBM - 字符数据表示体系结构 - 参考和注册,IBM SC09-2190-00,1996 年 12 月。

“字符集解密”,Andrea Vine,多语言计算与技术,第 10 卷第 4 期第 26 期,1999 年 8 月/9 月;ISSN 1523-0309;多语言计算公司,美国爱达荷州桑德波因特。

代码、密码和其他神秘和秘密通信 Fred B. Wrixon,ISBN 1-57912-040-7,黑狗与列文萨尔出版社,1998 年。

http://www.bobbemer.com/P-BIT.HTM IBM - EBCDIC 和 P 位;有史以来最大的计算机错误 Robert Bemer。

历史

2001 年 4 月 15 日:将 UTF-8 和 UTF-EBCDIC 添加到主表中,pvhp。

作者

Peter Prymmer [email protected] 于 1999 年和 2000 年编写了本文档,使用 CCSID 0819 和 0037,并得到了 Chris Leach 和 André Pirard [email protected] 以及 Thomas Dorner [email protected] 的 POSIX-BC 帮助。也感谢 Vickie Cooper、Philip Newton、William Raffloer 和 Joe Smith。本文档中使用的商标、注册商标、服务商标和注册服务商标均为其各自所有者的财产。

现在由 Perl5 Porters 维护。