[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS 用户手册


前页 目录 索引

12.12 理解符号替换

在某些上下文中,DCL 把其字符开始于字母的字符串用作一个符号名或词法函数。在这些上下文中,DCL 尝试用替换符号或词法函数的值来替换它的符号或词法函数。用符号的当前值替换该符号,称为符号替换。如果在任何其他上下文中使用符号或词法函数,那么必须使用一个替换运算符来请求符号替换。

当符号和词法函数用作如下情况时, DCL 自动对它们求值:

  • 在赋值 (=) 语句的右边
  • 在词法函数的变元中
  • 在 DEPOSIT、EXAMINE、IF 或 WRITE 命令中
  • 在命令行的开始,而这个字符串后面没有一个等号或冒号
  • 当执行子串替换或数字覆盖时,在赋值语句左边的中括号内 (请参阅 12.6.5 节)

在以下例子中,命令解释程序把开始于字母字符的任何字符串用作一个符号名,而把开始于数字或带基数运算符 (%) 的任何字符串用作一个文字数值。

  • 在以下例子中,COUNT 被自动识别并求值为一个符号:


    $ TOTAL = COUNT + 1
    
  • 在这个例子的第二行中,当符号 QUERY 与 F$LENGTH 函数一起使用时它被自动求值。另外,因为 F$LENGTH 函数是在赋值语句的右边,因此自动对它求值:


    $ QUERY = "Have we met before?"
    $ LEN = F$LENGTH(QUERY) + 5
    $ SHOW SYMBOL LEN
      LEN = 27   Hex = 0000001B  Octal = 000033
    
  • 在以下例子中,IF 命令把 A 和 B 用作符号名,并使用它们的当前值:


    $ IF A .EQ. B THEN WRITE SYS$OUTPUT "DONE"
    
  • 在这个例子的第二行中,命令解释程序自动用 PDEL 的当前值替换 PDEL,并执行作为结果的命令:


    $ PDEL = "DELETE SYS$PRINT/ENTRY="
    $ PDEL 181
    
  • 在以下例子中,DCL 自动把符号 BELL 定义为值 7,然后基于在赋值语句左边括入中括号内的值赋予一个新值。


    $ BELL = 7
    $ BELL[5,1] = 1
    $ SHOW SYMBOL BELL
     BELL = 39   Hex = 00000027   Octal = 00000000047
    

12.12.1 强制符号替换

要强制替换不在所列位置的符号,把这个符号括入省略号 (') 内,如下所示:


$ TYPE 'B'

要强制替换在引用字符串内的符号,在这个符号之前放置两个省略号 (') 并后跟单个省略号 ('),如下所示:


$ T = "TYPE ''B'"

处理一个命令行时,DCL 按以下次序用它们的值替换符号:

  • 强制替换
    从左至右,DCL 替换用省略号定界的所有字符串 (或者对于在引号内的字符串使用双省略号)。前面加上单个省略号的符号被迭代翻译;而对于前面加上双省略号的符号则不必。
  • 自动替换
    从左至右,DCL 求出命令行中的每个值,如果它是命令就执行它,而如果它是表达式就求出它的值。表达式中的符号被替换为它们的赋予值;这个替换不是迭代的。

以下例子示范 DCL 符号替换次序的效果。首先,定义符号 PN、FILE1 和 NUM:


$ PN = "PRINT/NOTIFY"
$ FILE1 = "[BOLIVAR]TEST_CASE.TXT"
$ NUM = 1

给出上述符号定义后,以下命令打印文件 [BOLIVAR]TEST_CASE.TXT:


$ FILE = "'FILE''NUM''"
$ PN 'FILE'

在第一个命令中,强制替换使 NUM 成为 1,使 FILE''NUM' 成为 FILE1。如果输入命令 SHOW SYMBOL FILE,可看到 FILE = " 'FILE1' "。

第二个命令执行两个替换。首先,'FILE' 被 'FILE1' 替换。'FILE1' 也需要替换,因为它括入省略号 (') 内。自动替换使 FILE1 成为 [BOLIVAR]TEST_CASE.TXT。然后,这个文件名附加到 PN 的值,即 PRINT/NOTIFY。作为结果的字符串如下所示:


$ PRINT/NOTIFY [BOLIVAR]TEST_CASE.TXT

12.12.2 符号替换运算符

在 DCL 通常不执行符号替换的位置,可以使用替换运算符请求符号替换。DCL 接受两个替换运算符:

  • 省略号 (')
  • 和号 (&)

这两个运算符的差别是发生替换的时间。前面加上省略号的符号在 DCL 命令处理的第一个阶段替换;而前面加上和号的符号在第二个阶段替换。有关命令处理阶段的详情,请参阅 12.13 节

省略号 (')

省略号 (') 是最频繁使用的替换运算符。当您使用符号代替命令参数或限定词时,使用它可请求符号替换。在字符串赋值 (:=) 语句的右边使用省略号可请求符号替换。

要在引用字符串内请求符号替换,把两个省略号放在符号名之前并把一个省略号放在它的后面。

当使用省略号请求符号替换时,不能在被替换值的中间续行 (使用连字号使字符续行)。

在以下例子中,TYPE 命令需要一个文件说明。省略号指出 LIT 是一个必须求值的符号。如果省略这个省略号,那么 DCL 寻找一个称为 LIT.LIS 的文件 (.LIS 是 TYPE 命令的默认文件类型):


$ LIT = "LIGHT.BILLS"
$ TYPE 'LIT'

在以下例子中,NAME 的值被替换,以便 FILE 成为 REPORT.DAT:


$ NAME := REPORT
$ FILE := 'NAME'.DAT
$ SHOW SYMBOL FILE
  FILE = "REPORT.DAT"

在以下例子中,符号 NAME 的当前值是 FRED:


$ MESSAGE = "Creating file ''NAME'.DAT"

因此,MESSAGE 有以下值:


Creating file FRED.DAT

和号 (&)

和号 (&) 也是一个命令解释程序能够识别的替换运算符。在很多情况下,省略号与和号执行同样的功能。当和号与省略号一起使用来影响替换执行的次序时,和号是更有效的替换运算符。

当符号未定义时命令解释程序采取的动作依赖于命令的上下文。有关详情,请参阅 12.13.5 节

这里展示的第一个命令中,命令处理的第一个阶段 (扫描),命令解释程序用其当前值替换符号名。命令处理的第二个阶段 (分析),第二个命令用其当前值替换符号名。尽管方法不同,但结果一样:


$ TYPE 'NAME'
$ TYPE &NAME

在以下例子中,和号 (&) 与省略号一起使用来影响替换次序:


$ P1 = "FRED.DAT"
$ COUNT = 1
$ TYPE &P'COUNT'

首先,命令解释程序对括入省略号内的符号 ('COUNT') 求值。其结果如下所示:


TYPE &P1

其次,命令解释程序对前面加上和号的符号 (P1) 求值。其结果如下所示:


TYPE FRED.DAT

在以下例子中,省略号与 P 和 COUNT 一起使用:


$ TYPE 'P''COUNT'

从左至右进行处理,命令解释程序尝试求出 P 的值。因为 P 是没有定义的符号,因此 DCL 给它一个空值。然后,它求出符号 COUNT 的值。其结果如下所示:


TYPE 1

在以下例子中,A 等于 B 的当前值:


$ B = "MYFILE.DAT"
$ A = "&B"
$ TYPE 'A'

当和号 (&) 用在引号 (" ") 内时,它不引起符号替换。因此,赋值时,不替换 B 的值。然而,TYPE 命令显示 MYFILE.DAT。因为命令解释程序首先把 A 替换为值 &B,因此发生这种情况。然后,它把符号 &B 替换为 MYFILE.DAT。如果重新定义了 B,那么 TYPE 命令的结果将因此更改。

使用和号时要遵守以下规则:

  • 把和号放在符号名之前,而不是之后。
  • 和号必须跟随一个定界符 (任何空白或特殊字符)。
  • 不能使用和号来请求替换括入引号 (" ") 内的字符串。
  • 不能使用和号来连接两个或更多的符号名。
  • 一般而言,在符号替换时不要使用和号,除非必需正确地翻译符号。

12.13 命令处理程序的三个阶段

命令解释程序分三个阶段执行符号替换。

12.13.1 第一阶段: 命令输入扫描

命令输入扫描 (也称为词法输入阶段),命令解释程序从左至右对前面加上省略号的符号求值。前面加上单个省略号符号被迭代翻译,如在第一阶段替换所述。前面加上两个省略号的符号不被迭代翻译。

12.13.2 第二阶段: 命令分析

在命令分析阶段中:

  • 命令解释程序分析命令行。它检查命令行中的第一个项目,查看它是否是一个符号。如果它是,就求出它的值。
  • 命令解释程序从左至右对前面加上和号的符号求值。

在这个阶段的符号替换是不迭代的。

12.13.3 第三阶段: 表达式求值

在表达式求值阶段:

  • 命令解释程序对前面加上 DEPOSIT、EXAMINE、IF 和 WRITE 命令的符号求值。
  • 命令解释程序对在词法函数中的符号求值。

在这个阶段的符号替换是不迭代的。

注意,命令解释程序不扫描被命令或在命令过程中执行的程序读取为输入数据的任何行。因此,命令解释程序不在这些数据行中执行符号替换。

在以下例子中,程序 AVERAGE 从 SYS$INPUT (命令输入流) 读取 55、57 和 9999。命令解释程序从不读取这些数据行。如果输入符号名作为输入,则对它们不求值:


$ RUN AVERAGE
55
57
9999

12.13.4 重复和迭代替换

符号替换可以重复或迭代:

  • 重复替换是指在单个命令行中发生一个以上类型的替换。
  • 迭代替换是指命令解释程序查看替换的值本身是否是一个符号。只在命令处理的第一个阶段翻译前面加上省略号的符号时,才发生迭代替换。

第一阶段替换

使用省略号 (') 请求符号替换时,命令解释程序在命令处理的第一个阶段执行迭代替换。

当符号包括在引用字符串内时,使用省略号的替换不迭代。

在以下例子中,替换是迭代的:


$ MAC = "5"
$ A = "'MAC'"
$ B = 'A'
$ SHOW SYMBOL B
  B = 5  Hex = 00000005  Octal = 00000000005

在语句 B = 'A' 之后,符号 B 的结果值是 5,因为:

  • 符号名 A 括入省略号内,因而用它的当前值 ('MAC') 替换它。
  • 因为这个值 ('MAC') 也括入省略号内,因此命令解释程序用它的当前值 (5) 替换 MAC。
  • 因为这个值 (5) 没有省略号,因此命令处理的第一个阶段就结束。没有必要在第二或第三阶段进行进一步的替换。因此,5 是符号名 B 的最后值。

然而,要注意在引用字符串中包括 A 的情形:


$ B = "''A'"
$ SHOW SYMBOL B
  B = "'MAC'"

在这种情况下,B 有值 'MAC'。因为在引用字符串中替换是不迭代的,因此符号名 A 只替换一次。

第二阶段替换

只当省略号在命令行中时,命令解释程序才自动执行迭代替换。有些情况下,您可能要嵌套命令同义字定义。

在以下例子中,处理 EXEC 时,命令解释程序只执行替换一次:


$ MAC = "TYPE A.B"
$ EXEC = "'MAC'"
$ EXEC

其结果是字符串 'MAC'。因为 MAC 不被识别为一个命令,因此命令解释程序显示一条出错消息。因为在命令处理的第一个阶段,没有替换被执行 (字符串 EXEC 没有被省略号定界),因此发生这个出错。在第二个阶段,因为 EXEC 是命令行的第一个值,因此字符串 'MAC' 被替换为 EXEC。这个替换不是迭代的。因此,即使用省略号定界 'MAC',也不执行附加的替换。

要正确地使用命令同义字 EXEC,把它括入省略号内:


$ 'EXEC'

在这种情况下,在命令处理的第一个阶段对符号 EXEC 求值。因为这个替换是迭代的,因此 ('MAC') 也被求值,并且替换为字符串 TYPE A.B。

第三阶段替换

当命令解释程序分析命令中的表达式时,在表达式中指定的任何符号只替换一次。然而,可以在表达式中使用省略号或和号,强制迭代替换。以这种方法强制迭代替换时,必须记住以下规则:

  • 在执行命令字符串之前,命令解释程序执行省略号和和号请求的所有替换。
  • 在命令处理的第一个和第二个阶段之后,自动执行符号替换的命令做这件事。

然而,要注意,如果替换的结果不是一个有效符号名,那么这个命令将失败。

以下例子展示 IF 命令中的迭代替换:


$ P1 = "FRED.DAT"
$ COUNT = 1
$ IF P'COUNT' .EQS. "" THEN GOTO END

当命令解释程序扫描这个命令行时,用它的当前值替换符号 COUNT。其结果如下所示:


IF P1 .EQS. "" THEN GOTO END

因为这个字符串没有省略号,因此命令解释程序不执行任何其他替换。然而,当 IF 命令执行时,它自动对符号名 P1 求值并把它替换为它的当前值。

在以下例子中,符号名 FILENAME 无效:


$ FILENAME = "A.B"
$ IF 'FILENAME' .NES. "" THEN TYPE 'FILENAME'

命令解释程序把符号 FILENAME 替换为它的当前值 (A.B)。其结果如下所示:


IF A.B .NES.  "" THEN TYPE A.B

当 IF 命令执行这个命令行时,因为 A.B 不是一个有效符号而出错。要正确地处理这个 IF 命令,可省略这个省略号,如下所示:


$ IF FILENAME .NES. "" THEN TYPE 'FILENAME'

12.13.5 未定义的符号

如果在命令行中使用的符号没有定义,命令解释程序或者显示一条出错消息,或者用空串替换这个符号,视上下文而定。其规则如下:

  • 在命令处理的第一个和第二个阶段,命令解释程序用空串替换所有前面加上省略号或和号的未定义符号。
  • 在命令处理的第三个阶段,如果命令解释程序发现一个未定义符号,它就显示一条警告消息并且不完成处理。

以下例子展示命令解释程序如何处理前面加上省略号的未定义符号:


$ FILE := MYFILE'FILE_TYPE'
$ SHOW SYMBOL FILE
  FILE = "MYFILE"
$ PRINT 'FILE'

建立符号 FILE 时,符号 FILE_TYPE 被替换为它的当前值。如果 FILE_TYPE 没有定义,那么命令解释程序用一个空串替换 FILE_TYPE。在文件说明中缺少文件类型使 PRINT 命令使用默认文件类型 .LIS。因而,这个文件说明被解释为 MYFILE.LIS。

在以下例子中,表达式在命令处理的第三个阶段求值:


$ A = 1
$ C = A + B
%DCL-W-UNDSYM, undefined symbol - check validity and spelling

符号 B 是未定义的,因而命令解释程序不能对这个表达式求值。

12.14 使用符号的备用方法: 自动外部命令

不用为过程定义符号,也可以从 DCL 级调用一个命令过程 (.COM 文件类型 ) 或可执行映象 (.EXE 文件类型)。使用自动外部命令,DCL 可以搜索特定目录集来查找命令过程或可执行映象,并自动运行它。

输入的命令动词不是一个 DCL 符号并且不在 DCL 命令表中时,系统通常显示以下消息:


DCL-W-IVVERB, unrecognized command verb - check validity and spelling

然而,如果逻辑名 DCL$PATH 已定义 (并且不是空白),那么 DCL 就执行 RMS $SEARCH 查找其文件名包含无效动词的任何文件,并且把 DCL$PATH:.* 用为默认文件说明。

如果 DCL 查找到一个 .COM 或 .EXE 文件,那么 DCL 将自动执行那个文件,并且把命令行的其余部分作为它的参数。(这个行为类似于 DOS、UNIX 和其他操作系统的 PATH 任选项。)

在以下例子中,不再需要 DCL 符号 SYSGEN。DCL 查看 SYS$SYSTEM 目录并查找 SYSGEN.EXE。DCL 的这种形为就象符号 "SYSGEN" 被定义为 "$SYS$SYSTEM:SYSGEN",它把 SYSGEN 映象激活为一个外部命令。


$ SYSGEN
%DCL-W-IVVERB, unrecognized command verb - check validity and spelling
 \SYSGEN\
$ DEFINE DCL$PATH SYS$SYSTEM,SYS$DISK:[]FOO
$ SYSGEN SHOW MAXPROCESSCNT
Parameter Name   Current   Default    Min.    Max.    Unit  Dynamic
--------------   -------   -------   ------- -------  ----  -------
MAXPROCESSCNT        157        32        12    8192 Processes

在以下例子中,SS 不必定义为 "@SS.COM",因为 DCL 将自动搜索 SYS$SYSTEM 目录来查找 SS.COM 或 SS.EXE。如果失败,DCL 就搜索当前目录来查找 SS.COM 或 SS.EXE。


$ TYPE SS.COM
$ SHOW SYMBOL/LOCAL/ALL
$ EXIT
$ SS "This is a parameter"
  P1 = "This is a parameter"
  P2 = ""
  P3 = ""
  P4 = ""
  P5 = ""
  P6 = ""
  P7 = ""
  P8 = ""
$ SS.EXE "This is a parameter"
  P1 = ".EXE"
  P2 = "This is a parameter"
  P3 = ""
  P4 = ""
  P5 = ""
  P6 = ""
  P7 = ""
  P8 = ""

在这个例子中,DCL 找出 SS.COM,其行为就象 "SS" 已被定义为 "@SS.COM" 的符号。激活的命令过程把命令行的其余部分分析为参数。注意,"SS.EXE" 不调用映象 SS.EXE,而是用两个参数来调用 SS.COM,其中第一个是文本串 ".EXE"。这与 OpenVMS 操作系统执行命令分析和符号替换的方法一致。


前页 后页 目录 索引