HP OpenVMS Systems Documentation

Content starts here

OpenVMS 用户手册


前页 目录 索引

12.14.1 使用自动外部命令

注意以下:

  • 逻辑名 DCL$PATH 可以是搜索列表类型逻辑。
  • 只使用每个逻辑名翻译的节点、设备和目录部分。
  • 发生正常的逻辑优先。通过用户自己的定义,用户可以取代 DCL$PATH 的系统定义。如果系统定义存在,而用户不想要这个特性,那么用定义 " " 取代这个逻辑而关掉它。
  • DCL 动词和符号名的有效字符集不同于文件名的有效字符集。例如,DCL 符号不能包含连字号 (-) 或开始于美元符 ($)。如果希望执行的映象或过程不是有效的 DCL 符号名,那么不能通过这个新特性直接调用它。
  • DCL 不分析这个命令。它让被调用的映象执行自己的命令分析。对于 C 程序,使用 main() 例行程序的 "argc" 和 "argv" 参数。对于用其他语言编写的程序,调用 LIB$GET_FOREIGN 可获得整个命令行,然后该程序必须分析它。
  • 如果一个目录包含命令过程和可执行映象,那么将调用第一个查找到的文件。在 OpenVMS 系统上,目录按字母顺序编目文件,因而将在 ".EXE" 文件之前找到 ".COM" 文件。如果在 DCL$PATH 逻辑名中有一个指向运行其他操作系统节点的网络文件说明,则可能在 ".COM" 文件之前找到 ".EXE" 文件。
    因为 DCL 执行搜索时把无效动词用作文件说明并把 "DCL$PATH:.*" 使用为默认文件说明,因此可能以这种查找特定文件的方法定义逻辑名。例如,如果把逻辑名 FOO 定义为 "FOO.EXE",并且在 DCL 提示下键入 "FOO",那么就决不能调用 FOO.COM,而只能是 FOO.EXE。

警告

如果您是特权用户,并且把您的默认设备和目录设置为其他用户帐户,就不要把 "SYS$DISK:[]" 放入 DCL$PATH 逻辑名的定义中。这样做将使 DCL  搜索当前目录,在那里搜索列表中的排字错误或不恰当地放置翻译将使当前目录的用户映象被发现,而被错误地以特权调用。

12.14.2 自动外部命令限制

注意以下限制:

  • 在 OpenVMS 操作系统 V6.2 之前的任何版本中,不能使用自动外部命令。
  • 因为新动词可以在任何时候都添加到 DCL 命令表,使用自动外部命令的命令以后某一天或许不能使用。
  • 自动外部命令特性不是在所有情况下都能正常工作。在以下例子中,DCL (只看任何动词的前四个字符) 查找匹配 SHOW 动词 (SHOWME 的前四个字母) 并执行 SHOW USERS 命令来代替 SHOWME.COM 过程。如果把 SHOWME 定义为 DCL 符号,那么 SHOWME 命令将调用 SHOWME.COM。


    $ DEFINE DCL$PATH SYS$SYSTEM,SYS$DISK:[]FOO
    $ TYPE SHOWME.COM
    $ SHOW SYMBOL P1
    $ EXIT
    $ SHOWME USERS
          OpenVMS 用户进程在 MARCH 2,1999 01:40 PM
        用户总数 = 1, 进程数 = 11
    
     用户名             交互      子进程   批量
     RSMITH              9         2
    


第 13 章
介绍命令过程

命令过程是一个包含 DCL 命令和 DCL 命令使用的数据行的文件。有些简单命令过程可以只包含一个或两个 DCL 命令;复杂的命令过程可以象复杂的计算机程序一样运行。当命令过程运行时,DCL 解释程序读取文件并执行它包含的命令。

如果系统管理员已设置一个系统注册命令过程,注册时它就执行。系统注册命令过程让系统管理员确保当您和其他用户注册系统时总要执行的某些命令。

在运行系统注册命令过程后,系统运行您的个性化注册命令过程 (如果存在)。个性化注册命令过程让您用户化计算环境。每次注册时就执行它包含的命令。注册时,系统可自动执行至多两个注册命令过程 (全系统的注册命令过程和您自己的注册命令过程,如果存在)。

为您设置帐户的人可以把注册命令过程放入您的顶级目录。如果注册命令过程不在您的顶级目录,那么您自己可以建立一个。把它命名为 LOGIN.COM 并把它放入您的顶级目录。除非系统管理员告诉您其他情况,否则注册时将运行您建立的 LOGIN.COM 文件。

本章分为以下几节:

  • 编写命令过程的基本信息
  • 编写命令过程的步骤
  • 执行命令过程
  • 退出、中断和出错处理命令过程
  • 注册命令过程

有两类 DCL 命令过程:

  • 简单
    按编写次序执行一串 DCL 命令
  • 复杂
    执行类似程序的功能

13.1 编写命令过程的基本信息

有两种方法建立命令过程:

  • 使用文本编辑程序,例如 EVE,建立新文件
  • 使用 DCL 命令 CREATE 建立新文件

建立的文件可以包含命令行、标号、注释、条件语句和变量。

13.1.1 默认文件类型

命令过程的默认文件类型是 .COM。命名命令过程时,如果指定 .COM 文件类型,那么只指定文件名就可以执行这个过程。SUBMIT 和执行过程 (@) 命令假定文件类型是 .COM,除非指定其他。

13.1.2 编写命令

以下是在命令过程中包括命令的建议:

  • 使用命令和限定词的完整名称。这将有助于确保命令过程与 OpenVMS 的将来发行版本兼容。
  • 使用续行使过程易于阅读。注意,续行不能从美元符开始。例如:


    $ PRINT LAB.DAT   -
         /AFTER=17:00 -
         /COPIES=20   -
         /NAME="COMGUIDE"
    

13.1.3 编写命令行

编写命令行时:

  • 必须使用一个美元符 ($) 开始每一行,包含命令、注释或标号。
  • 如果想要包括一个包含数据的行,那么在该行省略美元符 ($)。
  • 如果需要包括从一个美元符 ($) 开始的数据行,使用 DCL 命令 DECK 和 EOD。例如:


          $ ! Everything between the commands DECK and EOD
          $ ! is written to the file WEATHER.COM
          $ !
          $ CREATE WEATHER.COM
          $ DECK
          $ FORTRAN SUMMER
          $ LINK SUMMER
          $ RUN SUMMER
          $ EOD
          $ !
          $ ! Now execute WEATHER.COM
          $ @WEATHER
          $ EXIT 
     

注意,不从一个美元符开始的命令行可以被 DCL 正确地解释,但是 Compaq 强烈建议任何 DCL 命令行从一个美元符开始。

13.2 在命令行中使用标号

在 DCL 命令过程中,标号用于标记循环、代码段或子例行程序的开始。使用标号时,注意以下规则:

  • 把标号放在单独一行,使循环、子例行程序和条件代码更明显。
  • 使用包含少于 255 个字符并且没有空白空格的标号名。
  • 把标号放在美元符 ($) 之后并且把若干空格放在命令之前,可把标号与命令区别开来。
  • 用一个冒号结束每个标号。
  • 不能删除标号。

13.2.1 局部符号表中的标号

当命令解释程序遇到标号时,它把标号放入局部符号表的特殊节。标号可用的空间是有限的。如果一个命令过程使用许多符号,并且包含许多标号,那么命令解释程序可能用完符号表的空间而发出一条出错消息。如果发生这种情况,就在您的过程中包括 DELETE/SYMBOL 命令删除不再需要的符号。(然而,要注意不能删除标号。)

13.2.2 重复标号

如果命令过程使用同一标号一次以上,新定义就会替换局部符号表中的现有一个。

当重复标号存在时,GOTO 命令把控制传递给 DCL 最近处理的标号。处理重复标号时,GOTO 命令也使用以下规则:

  • 如果所有重复标号在 GOTO 命令之前,就把控制传递给离 GOTO 命令最近的标号。
  • 如果 GOTO 命令在重复标号之间,把控制传递给前面的离 GOTO 命令最近的标号。
  • 如果所有重复标号在 GOTO 命令之后,把控制传递给离 GOTO 命令最近的标号。

13.3 在命令过程中使用注释

把注释包括在命令过程中是好的编程习惯。当更新命令过程或解决故障时,注释是有用的。注释用途如下:

  • 在过程的开始描述过程和传递给它的参数。
  • 在每块命令的开始描述这段过程。
  • 使用包含美元符和感叹号 ($!) 的行分开命令序列。这使它易于阅读命令过程的大纲。如果插入空白行,那么命令解释程序就把它们解释为数据行,并且产生一条消息警告您这个数据行已被忽略。

在命令过程中编写注释时应用以下规则:

  • 使用感叹号 (!) 指出注释的开始;命令过程执行时,命令解释程序忽略感叹号右边的所有文本。
  • 要把文字感叹号包括在命令行中,把感叹号括入引号 (" ") 内。

13.4 如何编写命令过程

在开始编写命令过程之前,交互地执行命令过程将要执行的任务。键入必要的命令时,注意使用的任何变量和条件,和出现的任何循环。

以下几节包含编写简单命令过程的步骤。在这些节中使用的例子是命令过程 CLEANUP.COM。这个过程可以用来清除目录。

定义

  • 变量
    每次执行任务更改的数据。
  • 条件
    可以变化的任何一个或一组命令,因此每次执行任务时必须测试。
  • 循环
    重复执行直到满足条件的任何一个或一组命令。

13.5 编写命令过程的步骤

遵循以下步骤编写命令过程:

步骤 任务
1 设计命令过程。
2 赋值变量和测试条件。
3 添加循环。
4 结束命令过程。
5 测试和调试程序逻辑。
6 添加清除任务。
7 完成过程。

13.5.1 第 1 步: 设计命令过程

遵循以下步骤设计命令过程:
步骤 任务
1 决定过程将执行什么任务。
2 确定命令过程将要使用的任何变量,以及如何装入。
3 确定命令过程需要什么条件,以及如何测试。
4 决定如何退出命令过程。

某些命令通常是在清除操作期间执行。下表列出这些命令和它们执行的任务:

命令 执行的任务
DIRECTORY 显示当前目录的内容
TYPE filespec 显示文件
PURGE filespec 清除文件
DELETE filespec 删除文件
COPY filespec new-filespec 复制文件

变量

当执行任务时更改的任何数据是变量。如果在您的目录中建立或删除文件,那么每次清除目录时,文件名是不同的;因此,在 CLEANUP.COM 中的文件名是变量。

条件

每次执行命令过程时必须测试的任何命令被认为是条件语句。因为依赖于需要执行的操作,在 CLEANUP.COM 中的任何或所有命令也许执行,因此每个命令是条件语句。

设计决定

确定将在 CLEANUP.COM 命令过程使用什么变量和条件之后,必须决定如何装入变量、测试条件和退出命令过程。对于 CLEANUP.COM 命令过程,作出以下决定:

任务 如何完成
装入变量 命令过程从终端获得文件名。
测试条件 命令过程:
  • 从终端获得命令名,并基于命令名执行适当的语句。
  • 确保读入每个命令名的前两个字符,以区别 DELETE 和 DIRECTORY 命令。
退出循环 必须输入 EXIT 命令退出循环。

要使命令过程易于理解和维护,编写语句时使过程的执行从第一个命令到最后一个命令。

13.5.2 第 2 步: 变量赋值和条件测试

有许多方法赋值给变量。本节论述如何使用 INQUIRE 命令。有关其他方法,请参阅第 14 章

遵循以下步骤赋值给变量和测试条件:

步骤 任务
1 使用 INQUIRE 命令赋值给变量。
2 确定应该采用哪个动作。
3 使用 IF 和 THEN 语句测试条件。
4 编写程序桩,并把它插入到命令过程作为命令的占位符。
5 如果必要,编写出错消息。

13.5.2.1 使用 INQUIRE 命令

INQUIRE 命令提示一个值、从终端读取这个值并把这个值赋予一个符号。

按照默认,INQUIRE 命令:

  • 把回答转换为大写字母
  • 用单个空格替换多个空白和制表符
  • 除去前导和尾随空格
  • 如果应答包括符号或词法函数,就执行符号替换

在 CLEANUP.COM 中使用的以下命令行提示用户输入一个命令名。INQUIRE 命令把输入的值赋予符号 COMMAND。


$ INQUIRE COMMAND-
  "Enter command (DELETE, DIRECTORY, PRINT, PURGE, TYPE)"

13.5.2.2 保留文字字符

当使用 INQUIRE 命令时要保留小写字母字符、多个空格和制表符,把应答括入引号 (" ") 内。要把引号包括在应答中,就把引用的文本括入引号 (""text"") 内。

13.5.2.3 使用 IF 和 THEN 测试条件

在 INQUIRE 命令提示输入变量后,命令过程必须包括一个语句确定要采取什么动作。例如,要确定执行哪个命令,必须在命令过程中包括一些语句,从每个可能命令中识别用户输入的命令。

要测试一个条件是否为真,使用 IF 和 THEN 命令。下表展示必须在 CLEANUP.COM 中检查的可能性:

If... Then...
找到一个匹配, 执行这个命令。
没有找到一个匹配, 继续下一个命令。
在检查所有有效命令后没有找到一个匹配, 输出一条出错消息。

13.5.2.4 编写程序桩

程序桩是一个在测试设计时过程中使用的临时代码段。通常,程序桩输出一条消息声明它替换的函数。在全部设计工作都正确后,用正确的编码替换每个桩。

例子: 赋值变量和测试条件

以下例子展示如何赋值变量和测试条件:


$ INQUIRE COMMAND-
  "Enter command (DELETE, DIRECTORY, EXIT, PRINT, PURGE, TYPE)"
$ IF COMMAND .EQS. "EXIT" THEN EXIT
$!
$! Execute if user entered DELETE
$ DELETE:
$    IF COMMAND .NES "DELETE" THEN GOTO DIRECTORY         (1) (2)
$    WRITE SYS$OUTPUT "This is the DELETE section."       (3)
$! Execute if user entered DIRECTORY
$ DIRECTORY:                                              (4)
$    IF COMMAND .NES "DIRECTORY" THEN GOTO PRINT
$    WRITE SYS$OUTPUT "This is the DIRECTORY section."
   .
   .
   .
$! Execute if user entered TYPE
$ TYPE:
$    IF COMMAND .NES "TYPE" THEN GOTO ERROR               (5)
$    WRITE SYS$OUTPUT "This is the TYPE section."
$!
$ ERROR:
$    WRITE SYS$OUTPUT "You have entered an invalid command." (6)
$!
$ EXIT

当您检查这个例子时,注意以下各点:

  1. 这个 IF 语句测试查看用户输入的命令 (COMMAND) 是否等于 "DELETE"。如果 COMMAND 等于 DELETE,那么这个命令过程执行下一个命令。
  2. 这个语句也包括一个 GOTO 命令。GOTO 命令用来把执行流更改到这个过程的标号。在这种情况下,如果 COMMAND 不等于 DELETE,那么过程将执行 DIRECTORY 标号。
  3. 这个语句是程序桩。在命令过程逻辑被测试之后,这行将用 DELETE 操作需要的实际命令替换。
  4. 这是 DIRECTORY 子例行程序的标号。注意,标识每个命令块的标号与在任选项列表中的命令一样。这允许您在 GOTO 语句中使用符号 COMMAND (它等于用户的请求)。
  5. 这个 IF 语句测试是否输入了 "TYPE" 命令。如果输入了 "TYPE",则这个过程将输出 "This is the TYPE section"。然而,因为这个是您测试的最后命令,如果输入的命令不是 "TYPE",程序将显示一条出错消息。
  6. 如果测试了所有命令,并且没有找到有效的命令名,程序将输出 "You have entered an invalid command"。


前页 后页 目录 索引