[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS 用户手册


前页 目录 索引


第 14 章
DCL 高级编程

高级 DCL 编程包括使用复杂的命令过程和 DCL 命令 PIPE。如果您已阅读了第 13 章,并且具备 DCL 编程的基本知识,然后想要学习更多的高级方法,您就应该阅读本章。

复杂的命令过程可以执行类似程序的功能。在命令过程中可以使用变量输入、只当某些条件为真时才执行过程段、执行子例行程序或调用其他命令过程。

您也可以使用 DCL 命令 PIPE 执行类似程序的功能。例如,使用 PIPE 命令,可以在同一 DCL 命令行中执行一个或多个以下操作:

  • 流水线操作 (一串命令)
  • 输入/输出重定向
  • 多个和条件命令执行
  • 后台处理

本章包括以下信息:

  • 执行命令过程输入
  • 使用参数传递数据给嵌套的命令过程
  • 执行命令过程输出
  • 读取和写入文件 (文件 I/O)
  • 处理文件 I/O 出错
  • 控制执行流的技术
  • 建立新的命令级
  • 编写 Case 语句
  • 使用 PIPE 命令

14.1 执行命令过程输入

命令过程频繁地需要用户提供数据。这个数据,或输入,可以从交互 (如第 13 章所述) 或非交互地获得。本章论述非交互输入方法,以及不同于第 13 章所述的交互输入方法。

每次命令过程执行时,可以使用同样的数据。要做到这一点,把数据放置在命令过程中的数据行上,后面跟随需要这些数据的命令。

这个命令过程执行命令过程 CENSUS.EXE。这个过程每次执行时,CENSUS.EXE 读取数据 1993、1994 和 1995:


$ ! CENSUS.COM
$ !
$ RUN CENSUS
1993
1994
1995
$ EXIT

14.1.1 在命令过程中对包括数据的限制

DCL 把数据行上的文本直接传递给命令过程。 因此,它不处理必须翻译的数据,例如:

  • 符号
  • 逻辑名
  • 算术表达式

14.1.2 输入数据的其他方法

以下几节描述为命令过程获得输入数据的其他方法,包括:

  • 使用参数传递数据
  • 使用参数传递数据给批量作业
  • 使用参数传递数据给嵌套的命令过程
  • 使用 INQUIRE 和 READ 命令提示输入数据
  • 使用 SYS$INPUT 逻辑名获得数据

14.2 使用参数传递数据

下表包含把参数作为数据传递给命令过程的指引:

  • 把参数放在命令过程文件说明之后。
  • 可以传递最多 8 个参数给一个命令过程。
  • 如果传递少于 8 个参数值,那么多余的符号被赋值为空值。空值是不带字符的字符串,并且用引号 (" ") 表示。
  • 用一个或多个空格或制表符分隔参数 。

DCL 把传递给命令过程的参数放入局部符号 P1 至 P8。P1 赋值为第一个参数值,P2 为第二个,P3 为第三个,以此类推。例如,以下命令调用命令过程 SUM.COM,并把 8 个参数传递给这个过程:


$ @SUM 34 52 664 89 2 72 87 3

14.2.1 指定参数为整数

指定一个整数作为参数时,它被转换为字符串。在以下例子中,P1 是字符串值 24;P2 是字符串值 25:


$ @ADDER 24 25

可以在整数和字符串表达式中使用符号 P1 至 P8;DCL 自动执行必要的转换。

14.2.2 指定参数为字符串

要在字符串中保持空格、制表符或小写字母字符,把引号 (" ") 放在这个字符串之前和之后。例如:


$ @DATA "Paul Cramer"

在以下例子中,P1 是 Paul Cramer 而 P2 为空。如果省略引号,那么每个字符串被传递为独立的参数。例如:


$ @DATA Paul Cramer

在这个例子中,字符串 Paul 和 Cramer 被转换为大写字母;P1 是 PAUL 而 P2 是 CRAMER。

如另一个例子,如果用以下命令调用 DATA.COM:


$ @DATA  "Paul Cramer" 24 "(555) 111-1111")

P1 至 P8 在 DATA.COM 中定义如下:

P1 = Paul Cramer
P2 = 24
P3 = (555) 111-1111
P4--P8 = null

14.2.3 指定参数为符号

要传递一个符号的值,把省略号放在这个符号之前和之后。要保持符号值中的空格、制表符和小写字母字符,用三组引号括入这些值。您也必须使用三组引号包括作为字符串一部分的引号。

另一方法是把文本括入引号内,并且在符号出现处把两个省略号放在这个符号之前并且后面跟随一个省略号。

在以下例子中,由于传递符号给命令过程时 DCL 除去引号,因此 P1 是 Paul 并且 P2 是 Cramer:


$ NAME = "Paul Cramer"
$ @DATA 'NAME'

在以下例子中,P1 是 "Paul Cramer" 而 P2 为空:


$ NEW_NAME = """Paul Cramer"""
$ @DATA 'NEW_NAME'

在以下例子中,P1 翻译为 Paul Cramer:


$ ! DATA.COM
$ @NAME "''P1'"

14.2.4 指定参数为空值

要传递一个空参数,可在命令字符串中使用一组引号作为一个占位符。在以下例子中,传递给 DATA.COM 的第一个参数是一个空参数:


$ @DATA "" "Paul Cramer"

在这个例子中,P1 为空,而 P2 是 Paul Cramer。

14.3 使用参数传递数据给批量作业

要把参数传递给以批量模式执行的命令过程,可使用 SUBMIT 命令限定词 /PARAMETERS。

如果要使用单个 SUBMIT 命令执行一个以上命令过程,那么指定的参数用于在批量作业中的每个命令过程。

在以下例子中,命令传递三个参数给命令过程 ASK.COM 和 GO.COM,它们以批量作业方式执行:


$ SUBMIT/PARAMETERS=(TODAY,TOMORROW,YESTERDAY) ASK.COM,GO.COM)

在以下例子中,SUBMIT 命令传递两个参数给命令过程: LIBRARY.COM 和 SORT.COM:


$ SUBMIT-
_$ /PARAMETERS=(DISK:[ACCOUNT.BILLS]DATA.DAT,DISK:[ACCOUNT]NAME.DAT) -
_$ LIBRARY.COM,SORT.COM

批量作业的执行就象您已注册并且执行每个命令过程。这个 SUBMIT 命令执行一个在您的帐户下注册的批量作业,执行注册命令过程,然后执行以下命令:


$ @LIBRARY DISK:[ACCOUNT.BILLS]DATA.DAT DISK:[ACCOUNT]NAME.DAT)
$ @SORT DISK:[ACCOUNT.BILLS]DATA.DAT DISK:[ACCOUNT]NAME.DAT)

在命令过程中包括数据,或者把 SYS$INPUT 定义为一个文件,您也可以把数据传递给批量作业。指定的参数用于在批量作业中的每个命令过程。

14.4 使用参数传递数据给嵌套的命令过程

您可以传递多达 8 个参数给嵌套的命令过程。在嵌套过程中的局部符号 P1 至 P8 与调用过程的局部符号 P1 至 P8 是不相关的。

在以下例子中,DATA.COM 调用嵌套的命令过程 NAME.COM:


$ ! DATA.COM
$ @NAME 'P1' Joe Cooper

如果 DATA.COM 中的 P1 是字符串 Paul Cramer,它不包含引号,那么它作为两个参数传递给 NAME.COM。在 NAME.COM 中,P1 至 P8 定义如下:

P1 = PAUL
P2 = CRAMER
P3 = JOE
P4 = COOPER
P5--P8 = null

如果在 DATA.COM 中的 P1 是 "Paul Cramer" (包括引号),那么把 P1 括入 3 组引号内可以把这个值作为一个参数传递给 NAME.COM,如下所示:


$ ! DATA.COM
$ QUOTE = """
$ P1 = QUOTE + P1 + QUOTE
$ @NAME 'P1' "Joe Cooper"

在这个例子中,在命令过程 NAME.COM 中的 P1 是 Paul Cramer,而 P2 是 Joe Cooper。

14.5 提示输入数据

您可以使用 INQUIRE 命令 (如第 13 章所述) 或 READ 命令交互地获得命令过程数据。两个命令都提示输入并把应答赋值给一个符号。

READ 命令在以下方面不同于 INQUIRE 命令:

INQUIRE 命令... READ 命令...
提示输入值 提示输入值
从终端读取值 从第一个参数指定的来源读取值
给一个符号赋值 给名为第二个参数的符号赋值

READ 命令响应提示时接受在终端上键入的作为精确字符串值  的所有字符 (保持字母大小写、空格和制表符)。如果省略 /PROMPT 限定词,那么 READ 命令显示 Data: 作为默认提示。

您也可以编写这样的命令过程,即它们可以接受参数或者如果没有指定需要的参数时就提示用户输入。

在以下例子中,命令发出提示 Filename: 给终端,从逻辑名 SYS$COMMAND (按照默认,终端) 指定的来源读取应答,并且把应答赋值给符号 FILE:


$ READ/PROMPT="Filename: "  SYS$COMMAND  FILE

在以下例子中,当过程调用时如果没有指定一个文件名,就提示用户输入一个文件名:


$ ! Prompt for a file name if name
$ ! is not passed as a parameter
$ IF P1 .EQS. "" THEN INQUIRE P1 "Filename"
$ COPY 'P1' DISK5:[RESERVED]*.*
$ EXIT 

注意

如果您提交一个作为批量作业执行的命令过程,DCL 从 INQUIRE 命令之前的数据行读取在 INQUIRE 命令中指定的符号值。如果您不包括数据行,符号被赋予一个空值。

14.6 使用 SYS$INPUT 逻辑名获得数据

命令、公用程序和其他系统映象从逻辑名 SYS$INPUT 指定的来源获得它们的输入,这是默认输入流 在命令过程中,SYS$INPUT 被定义为命令过程文件;需要数据的命令或映象要在此文件中寻找数据行。然而,重定义 SYS$INPUT,您可以从终端或从独立的输入文件提供数据。

14.6.1 重定义 SYS$INPUT 为终端

您可以把 SYS$INPUT 重新定义为终端。这允许从命令过程调用的映象获得交互输入,而不是从命令过程中的数据行。

注意,如果想要在命令过程中使用需要交互输入的 DCL 命令或公用程序,必须把 SYS$INPUT 重新定义为终端。

在以下例子中,命令过程允许您交互地提供输入给映象 CENSUS.EXE:


$ ! Execute CENSUS getting data from the terminal
$ DEFINE/USER_MODE SYS$INPUT SYS$COMMAND
$ RUN CENSUS
$ EXIT 

CENSUS.EXE 运行时,DEFINE/USER_MODE 命令临时重新定义 SYS$INPUT,因而 CENSUS.EXE 从终端获得它的输入。在 CENSUS.EXE 完成 之后,SYS$INPUT 回复到它的原始定义 (命令过程文件)。

在以下例子中,命令过程把 EVE 用作文本编辑程序:


$ ! Obtain a list of your files
$ DIRECTORY
$ !
$ ! Get file name and invoke the EVE editor
$ EDIT_LOOP:
$      INQUIRE FILE "File to edit (Press Return to end)"
$      IF FILE .EQS. "" THEN EXIT
$      DEFINE/USER_MODE SYS$INPUT SYS$COMMAND
$      EDIT/TPU 'FILE'
$      GOTO EDIT_LOOP 

命令过程提示输入文件名,直到按下 Return 键终止这个循环。输入文件名时,过程自动调用 EVE 来编辑这个文件。运行这个编辑程序时,SYS$INPUT 被定义为终端,因而可以交互地输入编辑。

14.6.2 定义 SYS$INPUT 为一个单独的文件

把 SYS$INPUT 定义为一个文件,命令过程也可以从文件获得输入。注意,DCL 不处理数据行;命令过程直接把数据行上的文本传递给命令或映象。如果在数据行上包括 DCL 符号或表达式,DCL 不会替换这个符号的值或者求值表达式。如果在数据行中使用感叹号 (!),那么您传递数据给它的映象会处理这个感叹号 。

把数据文件的名称指定为 SYS$INPUT,您也可以把程序放入命令过程文件中。这导致编译程序从命令过程读取程序,而不是从另一个文件。

以下例子展示一个命令过程,它包含一个 FORTRAN 命令,并且后面跟随程序的语句:


$ FORTRAN/OBJECT=TESTER/LIST=TESTER SYS$INPUT
C  THIS IS A TEST PROGRAM
   A = 1
   B = 2
   STOP
   END
$ PRINT TESTER.LIS
$ EXIT

FORTRAN 命令使用逻辑名 SYS$INPUT 标识编译的文件。由于 SYS$INPUT 等同于这个命令过程,因此 FORTRAN 编译程序编译这个 FORTRAN 命令之后的语句 (直至下一个开始于美元符的命令行)。编译完成时,建立两个输出文件: TESTER.OBJ 和 TESTER.LIS。然后,PRINT 命令打印这个文件。

14.7 执行命令过程输出

命令过程的输出,如数据、出错消息和命令行校验,可以被指引到终端或其他文件。本节论述以下指引输出的方法:

  • 显示数据
  • 重定向命令和映象的输出
  • 从命令过程返回数据
  • 重定向出错消息

14.7.1 显示数据

使用 TYPE 命令显示有几行长并且不需要符号替换的文本。TYPE 命令把您指定文件的数据写入 SYS$OUTPUT。

在以下例子中,SYS$INPUT 被指定为数据文件。TYPE 命令从数据行读取数据,并在终端上显示这些行。


$ ! Using TYPE to display lines
$ TYPE SYS$INPUT
REPORT BY MARY JONES
PREPARED APRIL 15, 2002
SUBJECT: Analysis of Tax Deductions for 2002
   .
   .
   .
$ EXIT

使用 WRITE 命令写入包含符号或词法函数的数据。除非把数据括入引号 (" ") 内,否则 WRITE 命令自动执行符号替换。

要使用 WRITE 命令把字符串显示为文字文本,把字符串括入引号 (" ") 内。例如:


$ WRITE SYS$OUTPUT "Two files are written."
Two files are written.

要在字符串中包括引号,使用两组引号 ("" "")。例如:


$ WRITE SYS$OUTPUT "Summary of ""Q & A"" Session"
Summary of "Q & A" Session

要在一行以上继续一行文本,用一个加号 (+) 和连字号 (-) 连接这两个字符串。例如:


$ WRITE SYS$OUTPUT "Report by Mary Jones" + -
" Prepared April 15, 2002"
Report by Mary Jones Prepared April 15, 2002

WRITE 命令自动执行符号替换,并显示符号的值。要在字符串内强制符号替换,把符号括入省略号内。例如:


$ AFILE = "STAT1.DAT"
$ BFILE = "STAT2.DAT"
$ WRITE SYS$OUTPUT "''AFILE' and ''BFILE' ready."
STAT1.DAT and STAT2.DAT ready.

在这个例子中,STAT1.DAT 是符号 AFILE 的翻译;STAT2.DAT 是符号 BFILE 的翻译。

14.7.2 重定向命令和映象的输出

命令、公用程序和其他系统映象把它们的输出写入逻辑名 SYS$OUTPUT 指定的来源。按照默认,SYS$OUTPUT 等同于终端。然而,可以按以下方法之一重定向输出:

  • 调用这个命令时,使用 /OUTPUT 限定词。接受 /OUTPUT 限定词的 DCL 命令包括: ACCOUNTING、CALL、DIRECTORY、HELP、LIBRARY、RUN (进程)、SPAWN 和 TYPE。
  • 使用 DEFINE/USER_MODE 命令,临时把 SYS$OUTPUT 重新定义为一个文件。
  • 临时把 SYS$OUTPUT 定义为一个空设备 (使用 DEFINE/USER_MODE 命令),可抑制命令的输出。

在以下例子中,命令过程把 SHOW USERS 命令的输出重定向到一个文件。只在执行 SHOW USERS 命令时,SYS$OUTPUT 新定义才有效。


$ DEFINE/USER_MODE SYS$OUTPUT SHOW_USER.DAT
$ SHOW USERS
$ !
$ ! Process the information in SHOW_USER.DAT
$ OPEN/READ INFILE SHOW_USER.DAT
$ READ INFILE RECORD
   .
   .
   .
$ CLOSE INFILE
$ EXIT

在以下例子中,SYS$OUTPUT 定义为一个空设备 (NL:)。


$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ APPEND NEW_DATA.DAT STATS.DAT
   .
   .
   .

/USER_MODE 限定词用来建立一个临时逻辑名赋值,它只是在下一个映象完成之前才有效。在这个命令执行之后,SYS$OUTPUT 回复到默认定义 (通常是终端)。

您不能使用 DEFINE/USER_MODE 命令重定向在命令解释程序内执行的 DCL 命令的输出。作为代替,使用 DEFINE 命令重新定义 SYS$OUTPUT,并且使用 DEASSIGN 命令删除不再使用的定义。

下表完整列出在命令解释程序内执行的 DCL 命令:

= ALLOCATE ASSIGN
ATTACH CALL CANCEL
CLOSE CONNECT CONTINUE
CREATE/LOGICAL_NAME_TABLE DEALLOCATE DEASSIGN
DEBUG DECK DEFINE
DEFINE/KEY DELETE/SYMBOL DISCONNECT
ELSE ENDIF ENDSUBROUTINE
EOD EXAMINE EXIT
GOSUB GOTO IF
INQUIRE ON OPEN
READ RECALL RETURN
SET CONTROL SET DEFAULT SET KEY
SET ON SET OUTPUT_RATE SET PROMPT
SET PROTECTION/DEFAULT SET SYMBOL/SCOPE SET UIC
SET VERIFY SHOW DEFAULT SHOW KEY
SHOW PROTECTION SHOW QUOTA SHOW STATUS
SHOW SYMBOL SHOW TIME SHOW TRANSLATION
SPAWN STOP SUBROUTINE
THEN WAIT WRITE

以下例子展示将用来把 SHOW TIME 命令的输出重定向到文件 TIME.DAT 的命令。在解除赋值 SYS$OUTPUT 之后,它又回复到默认定义 (终端)。


$ DEFINE SYS$OUTPUT TIME.DAT
$ SHOW TIME
$ DEASSIGN SYS$OUTPUT


前页 后页 目录 索引