OpenVMS 用户手册
9.2 排序文件
要排序文件,使用 DCL 命令 SORT。指定要排序文件名,用逗号分开,后面跟随排序后建立的输出文件的名称。
可选地,可以为想要排序的每个字段指定一个键。每个键包括以下信息:
- 记录中键字段的开始位置 (必需的)
- 键的大小 (必需的)
- 键的数据类型
- 记录排序的次序
- 键的优先级
如果不指定任何键,Sort 假定只有一个键,并且这个键字段是:
- 在记录的第一个位置开始
- 包括整个记录
- 包含字符数据
- 按升序排序
以下两个例子使用默认键。
- 在这个例子中,文件 NAMES.LST 按升序排序:
$ SORT NAMES.LST BYNAME.LST
|
这个命令建立已排序的输出文件 BYNAME.LST,如图 9-1
所示。
图 9-1 按升序排序的列表
- 在这个例子中,文件 NAMES.LST 和 NAMES2.LST 被排序到已排序的输出文件 BYNAME.LST。Sort 对待这些文件就象它们是一个大文件:
$ SORT NAMES.LST,NAMES2.LST BYNAME.LST
|
有关 SORT 限定词的完整列表,请参阅 9.9 节。9.2.1 定义键
使用 /KEY
限定词定义一个键。指定多个键时,为每个键使用一个独立的 /KEY 限定词。
表 9-2 描述组成键的 5 个元素。
表 9-2 /KEY 限定词值
键元素 |
值 |
描述 |
键位置
|
POSITION:
n
|
键字段的第一个字节在记录中的位置。记录第一个字节的位置是 1。POSITION:
n 是必需的。 |
键大小
|
SIZE:
n
|
键字段的长度。SIZE:
n 是必需的,浮点数据除外。 指定大小时,为键指定的数据类型确定什么值是可接受的。下表列出每类数据的可能值,和用来指定键大小的单位。
数据 |
有效范围 |
单位 |
字符
|
1 至 32,767
|
字符
|
二进制
|
1、2、4、8 或 16 (对于高性能 Sort/Merge 公用程序,二进制数据类型的键大小必须是 1、2、4 或 8 字节。对 16
字节二进制键的支持留待将来的 OpenVMS Alpha 发行版本。)
|
字节
|
十进制
|
1 至 31 |
数字
|
浮点
|
不需要值。 |
对于十进制数据,如果十进制符号存储在一个单独字节,那么这个字节不计入数据大小的计数中。 如果指定的键超出记录的末端,Sort
则把缺失的字符当作空字符。 |
数据类型
|
CHARACTER
|
字符数据。CHARACTER 是默认数据类型。 |
|
BINARY
|
二进制数据。
SIGNED --- 有符号的二进制或十进制数据。SIGNED 是二进制和十进制数据的默认格式。 UNSIGNED ---
无符号的二进制或十进制数据。 |
|
F_FLOATING
|
F_FLOATING 格式数据。
|
|
D_FLOATING
|
D_FLOATING 格式数据。
|
|
G_FLOATING
|
G_FLOATING 格式数据。
|
|
H_FLOATING
|
在 VAX 系统上,H_FLOATING 格式数据。(高性能 Sort/Merge 公用程序当前不支持。)
|
|
S_FLOATING
|
在 Alpha 系统上,IEEE S_FLOATING 格式数据。
|
|
T_FLOATING
|
在 Alpha 系统上,IEEE T_FLOATING 格式数据。
|
|
DECIMAL
|
十进制数据。
TRAILING_SIGN --- 尾随符号的十进制数据。TRAILING_SIGN 是十进制数据的默认格式。
LEADING_SIGN --- 前导符号的十进制数据。前导符号必须在字段的第一个位置,而这个字段必须左侧无填补符。 OVERPUNCHED_SIGN ---
超额打孔的十进制数据。OVERPUNCHED_SIGN 是十进制数据的默认格式。
SEPARATE_SIGN --- 单独符号的十进制数据。 |
|
ZONED
|
分区的十进制数据。(高性能 Sort/Merge 公用程序当前不支持。)
|
|
PACKED_DECIMAL
|
压缩的十进制数据。
|
排序次序
|
ASCENDING
|
按递增的字母或数字次序进行排序操作。ASCENDING 是默认次序。 |
|
DESCENDING
|
按递减的字母或数字次序进行排序操作。
|
键优先级
|
NUMBER:
n
|
如果没有按照它们的优先级次序列出多个键,则通过它可指定每个键的优先级次序。可指定值从 1 至 255。 |
如果键字段的数据不是字符数据,必须指定其数据类型。Sort/Merge 公用程序识别以下数据类型:
BINARY,[SIGNED]
|
|
BINARY,UNSIGNED
|
|
CHARACTER
|
|
DECIMAL,LEADING_SIGN,SEPARATE_SIGN [SIGNED]
|
|
DECIMAL,LEADING_SIGN,[OVERPUNCHED_SIGN,SIGNED]
|
|
DECIMAL [,SIGNED,TRAILING_SIGN,OVERPUNCHED_SIGN]
|
|
DECIMAL,[TRAILING SIGN],SEPARATE_SIGN,[SIGNED]
|
|
DECIMAL,UNSIGNED
|
|
D_FLOATING
|
|
F_FLOATING
|
|
G_FLOATING
|
|
H_FLOATING
|
|
S_FLOATING,IEEE (只用于 Alpha 系统)
|
|
T_FLOATING,IEEE (只用于 Alpha 系统)
|
|
PACKED_DECIMAL
|
|
ZONED
|
|
在中括号内的项目是默认的,不需要指定。
注意
对于十进制字符串数据,Sort/Merge 公用程序为 VAX 和 Alpha
系统报告在输入串中有一个无效数字是不同的。在 VAX
系统上,您会接收到一条消息,告知为了比较把无效数字 (或保留操作数) 转换为有效的十进制字符串。在 Alpha 系统上,Sort/Merge 执行同样的转换,但不显示这条消息。在两种情况下,都把输入文件的数据不更改地写入输出文件。 |
在图 9-2 中,文件 EMPLOYEE.LST 的每个记录包括
3 个字段: (1) 部门名、(2) 帐号和 (3) 雇员名。
图 9-2 列表中的记录字段
以下例子说明当使用或不使用一个键字段时,如何排序 EMPLOYEE.LST 中的记录:
- 在这个例子中,使用 /KEY 限定词描述帐号字段,按帐号排序 EMPLOYEE.LST:
$ SORT/KEY=(POSITION:5,SIZE:4,DECIMAL) EMPLOYEE.LST BILLING1.LST
|
这个命令指定键字段 (帐号)
开始于位置 5,是 4 个字符长,包含十进制数据,并且应该按升序排序 (默认)。图 9-3
展示这个排序操作的结果。
图 9-3 按键字段排序
- 这个例子展示没有指定键字段时,如何排序文件 EMPLOYEE.LST:
$ SORT EMPLOYEE.LST BYDEPT.LST
|
因为没有指定键,排序假定默认特征。图 9-4
展示这个排序操作的结果。
图 9-4 用默认键记录排序
Sort 把 EMPLOYEE.LST
的每个记录视为字符数据的一个键。在这个例子中,每个记录包括一个部门名、一个帐号和一个雇员名。如果
Sort
找到重复的部门名,它就按帐号排序部门名。如果它找到重复的复制帐号,它就按雇员名排序。注意,帐号是记录的一部分。除非另外指定,它被视为字符数据。
9.2.2 多键字段
排序可以使用一个以上的键 (多达 255 个键的极限)。可以按它们的优先级次序指定多个键:第一个是主键,下一个是辅助键,等等。另外,可以使用 NUMBER:n 指定键的优先级。每个键可以递增或递减。 在以下例子中,文件 EMPLOYEE.LST
排序首先按照雇员名键,然后 (当有同名记录时) 按照帐号键:
$ SORT /KEY=(POSITION:10,SIZE:15,CHARACTER) -
_$ /KEY=(POSITION:5,SIZE:4,DECIMAL) EMPLOYEE.LST BILLING2.LST
|
图 9-5 展示这个排序操作的结果。
图 9-5 用多键字段排序
在以下例子中,记录排序时首先按部门名的降序,然后按雇员名的升序:
$ SORT/KEY=(POSITION:1,SIZE:3,DESCENDING) -
_$ /KEY=(POSITION:10,SIZE:15) -
_$ EMPLOYEE.LST BILLING3.LST
|
图 9-6 展示这个排序操作的结果。
图 9-6 用多键字段排序 (升序和降序)
9.2.3 同样的键字段
按照默认,Sort/Merge 保留带同样键字段的记录,但是不维持它们在输入文件中出现的同样次序。要控制同键记录排序的方法,可指定以下限定词之一:
- /STABLE
维持同键记录的输入次序。当排序多个输入文件时如果使用这个限定词,那么输出同键记录时,第一个文件的同键记录在第二个文件的同键记录之前,以此类推。 - /NODUPLICATES
只保留同键记录的一个副本。如果想要指定保留哪个重复记录,那么在程序级调用
Sort 并指定一个等键例行程序。
/STABLE 和 /NODUPLICATES
限定词是不兼容的。在同一命令行中不能同时指定这两个限定词。
在以下例子中,从文件 EMPLOYEE.LST 中剔除重复帐号的记录:
$ SORT /KEY=(POSITION:5,SIZE:4)/NODUPLICATES EMPLOYEE.LST BUDGET.LST
|
图 9-7 展示这个排序操作的结果。
图 9-7 用同样的键字段排序
9.2.4 非字符数据
如果排序的记录包含非字符数据的项目,则指定每个键的数据类型。另外,小心地计算开始位置和大小,因为比较的项目可以占用 1 个以上字节。
如果要排序的文件记录包含 20 个字符后面跟随 3
个 F_floating 格式的浮点数,那么其位置如下所示:
- 字符数据占用位置 1 至 20 (20 个字符)。
- 第一个 F_floating 浮点数占用位置 21 至 24。
- 第二个 F_floating 浮点数占用位置 25 至 28。
- 第三个 F_floating 浮点数占用位置 29 至 32。
要按第三个浮点数排序文件,指定键字段如下:
$ SORT/KEY=(POSITION:29,F_FLOATING) STATS.RAW STATS.SOR
|
不需要指定浮点数的大小,因为它是固定四个字节。9.2.5 输出文件组织
按照默认,排序产生一个输出文件,其文件组织与第一个输入文件相同。要指定不同的输出文件组织,可在 Sort 命令行中,在输出文件说明之后包括以下限定词之一:
- /FORMAT (记录格式)
当使用这个输出限定词时,可以定义文件记录格式、长度和块大小。 - /INDEXED_SEQUENTIAL
使用这个限定词,可以定义输出文件具有索引顺序文件组织。如果指定索引顺序作为输出文件组织,还必须完成以下步骤:
- 在执行 Sort 操作之前,建立一个作为输出文件的空文件。Sort 需要一个已经存在的输出文件,并且是空的。
- 在 SORT 命令行中,在输出文件名之后包括 /OVERLAY 限定词。/OVERLAY
限定词指出现有文件要被输入文件的排序记录覆盖。
- /RELATIVE
使用这个限定词,可以定义输出文件有相对文件组织。 - /SEQUENTIAL
使用这个限定词,可以定义输出文件有顺序文件组织。
在以下例子中,在索引顺序文件 EMPLOYEE.LST 排序之后产生一个顺序文件:
$ SORT/KEY=(POSITION:10,SIZE:15) -
_$ EMPLOYEE.LST BYNAME.LST/SEQUENTIAL
|
9.2.6 排序进程
Sort 安排文件时使用以下内部进程之一: 记录、标签、地址或索引。(高性能 Sort/Merge
公用程序只支持记录进程。对标签、地址和索引进程的实现留待将来的 OpenVMS Alpha 发行版本。) 指定的进程可以影响 Sort 操作的效率。有关优化 Sort 或 Merge 操作的详情,请参阅
9.8 节。
下表描述四类进程。使用
/PROCESS=type 限定词可指定排序进程。
排序进程 |
类型 |
描述 |
记录
|
RECORD
|
排序时保持记录原样,并且产生一个包含完整记录的输出文件。记录是默认排序进程。 |
标签
|
TAG
|
只排序键字段,然后重新读取输入文件,产生一个包含完整记录的输出文件。其结果与一个完整记录排序一样。 如果磁盘空间很少,标签排序是有用的,因为在排序期间它通常使用较少的工作文件空间。在大多数情况下,标签排序比记录排序慢,因为它需要额外的时间重新读取输入文件。 |
地址
|
ADDRESS
|
只排序键字段,并且产生一个输出文件,这个文件是以二进制格式存储的记录文件地址 (RFA) 的索引。 地址排序比记录排序快,但是必须编写一个程序使记录地址与输入文件的记录关联。 |
索引 |
INDEX
|
只排序键字段,并且产生一个包含键和 RFA 的输出文件
(以二进制格式)。 与地址排序一样,索引排序比记录排序快,但是必须编写一个程序使记录地址与输入文件的记录关联。
|
9.3 指定比较顺序
字符根据比较顺序排序。对于包含字符数据的文件,可以使用
/COLLATING_SEQUENCE=sequence 限定词来指定比较顺序。下表描述比较顺序任选项:
比较顺序 |
顺序 |
描述 |
ASCII
|
ASCII
|
字符数据的默认比较顺序。ASCII 顺序先是数字 (0 至 9),然后是大写字母 (A 至 Z),最后是小写字母 (a 至 z)。 |
EBCDIC
|
EBCDIC
|
产生一个按 EBCDIC 顺序排序的输出文件。数据仍然是 ASCII 表示。EBCDIC
顺序先是小写字母 (a 至 z),然后大写字母 (A 至 Z),最后是数字 (0 至 9)。
|
DEC 多国字符集
|
MULTINATIONAL
|
多国比较顺序根据 DEC 多国字符集比较字符 (请参阅附录 A)。在MULTINATIONAL
字符顺序中,字符根据以下规则排序:
- 所有读音格式的字符具有这个字符的比较值 (如,A'、A" 和 A` 比较为 A)。
- 小写字母字符与它们的大写字母具有相同的比较值 (如,a
比较为 A,而 a" 比较为 A")。
- 如果两个字符串比较为相同,就执行分解比较。继续比较字符串来检测由于区别音符、忽略的字符或虽然比较相同但实际上不同字符而导致的差别。如果字符串仍然比较为相同,那么就比较字符的数字代码。在最终比较后,小写字母字符排序在大写字母之前。
|
国家字符集 (NCS)
|
比较顺序名
|
命名的比较顺序必须定义在 NCS 库中。有关详情,请参阅 OpenVMS
National Character Set Utility Manual。 (高性能 Sort/Merge 公用程序不支持国家字符集 (NCS) 比较顺序。
对 NCS 比较顺序的支持留待将来的 OpenVMS Alpha 发行版本。)
|
用户自定义顺序
|
(顺序字符串)
|
指定一个用户自定义的比较顺序。用户自定义比较顺序只支持说明文件,而不支持命令行界面。 (高性能 Sort/Merge
公用程序不支持用户自定义的比较顺序。对用户自定义比较顺序的支持要留待将来的 OpenVMS Alpha 发行版本。) |
|
|
指定一个单字符、双字符或单字符范围的字符串,可定义一个比较顺序。(双字符是任何两个单字符的集合,比较时就象它们是一个字符。例如,"CH" 可以定义成比较为 "C"。) 这个字符串应该括入圆括号内。 也可以用其相应的八进制、十进制或十六进制值表示字符,但要使用基数运算符: %O、%D 和 %X。
当定义自己的比较顺序时,必须注意以下规则:
- 把字符括入引号 ("") 内。
- 用逗号 (,) 分开每个字符和字符范围,并把整个列表括入圆括号内。
- 为出现在 Sort 或 Merge 操作的字符键的所有字符给出比较值。任何没有比较值的字符将被忽略,除非指定 FOLD 或 MODIFICATION 任选项。
- 不要多次定义一个字符。
- 不要使用引号 ("")
指定空字符。改为使用基数运算符,如 %X0。
- 要指定引号,可把它们括入另一组引号 ("" "") 内,或者使用一个基数运算符。
以下字符串定义一个比较顺序,其中,双字符 LL 比较为一个在 L 和 M 之间的单字符。("A"-"L","LL","M"-"Z")
|
注意
当使用多国比较顺序排序或合并文件以作进一步处理时,要谨慎使用。在大多数程序设计语言中的顺序检查过程比较数字字符。因为多国顺序基于实际的图形字符,而不是表示那些字符的代码,因此常规的顺序检查将失效。 |
以下例子示范使用说明文件建立用户自定义的比较顺序。有关说明文件的详情,请参阅
9.7 节。
-
/COLLATING_SEQUENCE=(SEQUENCE=ASCII,IGNORE=("-"," "))
|
这个 /COLLATING_SEQUENCE 限定词及指定的 IGNORE 任选项,导致以下字段在分解之前比较为相同:
252-3412
252 3412
2523412
|
-
/COLLATING_SEQUENCE=(SEQUENCE=("A"-"L","LL","M"-"R","RR","S"-"Z"))
|
这个 /COLLATING_SEQUENCE 限定词定义了一个顺序,在此顺序下,双字符 LL 比较为在 L 和 M 之间的一个单字符,而双字符
RR 比较为在 R 和 S
之间的一个单字符。另外,这些双字符也按通常的字母顺序出现。按照默认,这个用户自定义顺序不定义任何其他字符,如小写字母 a 至 z。
|