【问题标题】:OpenVMS - DELETE Line if TEXT like xOpenVMS - 如果文本像 x,则删除行
【发布时间】:2014-03-12 17:17:48
【问题描述】:

我有一个批处理脚本,它将所有文件(包括路径和版本号)写入物理设备的 TMP 文件。然后,此批处理脚本会写入任何显示文件版本号大于提供的变量的行。

DIRECTORYX := DIRECTORY /NODATE /NOHEADING /NOTRAILING
DIR_OUTPUT_FILENAME = "TOPAS$UTILLOG:" + F$UNIQUE() + ".TMP"
DEVICE = $1$DGA1112
DIRECTORYX 'DEVICE':[000000...]*.*;* /NOSIZE /OUTPUT='DIR_OUTPUT_FILENAME'

同时,我有一些我不感兴趣的文件被报告给我。在这种情况下,我想从 TMP 文件中删除任何可能包含此文件名 (filename.ext;) 的行,以便批处理脚本可以继续通过它并且只报告我不明确想要的文件忽略。

如何在循环中使用“IGNORE_FILE”作为文本字符串的变量来读取文件,以匹配并删除关联的文本行,以便当我的批处理脚本继续执行文件时它不会报告文件请求被忽略。

非常感谢您的帮助

【问题讨论】:

  • f$locatef$match_wild 应该能够处理匹配。如果你想变得更高级,可以使用f$parse 将字符串分解成不同的组件。
  • 我不确定我是否理解您想要实现的目标。从 TMP 文件中删除 filename.ext 似乎等同于不写入它:目录具有 /exclude 限定符。并且搜索有一个 /match=nor 限定符,搜索 filename.ext 会将这些文件从搜索结果中排除。

标签: openvms dcl


【解决方案1】:

好吧...现在我知道你从哪里来了。

我将如何写从第 7 到行尾的所有内容?

好吧,您可以从 i=7 开始循环,或者您可以使用“引号”字符串并将引号用作新的分隔符。这是两者的示例,使用双引号作为几乎自然的第二分隔符选择

$
$ READ SYS$INPUT BUFF
SHG101,$1$DGA1101:,25,15,10,5000,100,X.TMP,Y.DAT
$
$ excludes = ""
$ tmp = F$ELEMENT(7, ",", BUFF)
$ IF tmp.NES.","
$ THEN
$   i = 8
$   excludes = tmp
$exclude_loop:
$   tmp = F$ELEMENT(i, ",", BUFF)
$   IF tmp.NES.","
$   THEN
$      excludes = excludes + "," + tmp
$      i = i + 1
$      GOTO exclude_loop
$   ENDIF
$   excludes = "/EXCLUDE=(" + excludes + ")"
$ ENDIF
$
$ SHOW SYMB excludes
$
$! Using a different delimitor:
$ READ SYS$INPUT BUFF
SHG101,$1$DGA1101:,25,15,10,5000,100,"X.TMP,Y.DAT"
$
$ excludes = ""
$ tmp = F$ELEMENT(1, """", BUFF)
$ IF tmp.NES."," THEN excludes = "/EXCLUDE=(" + tmp + ")"
$
$ SHOW SYMB excludes

在我们看到的代码中: 检查“设备”是否有高文件版本 (>= ;''HVERNO') - 可能需要一些时间...>

我敦促您查看 DFU 大循环代码“READ FH3 /END_OF_FILE=LABEL$_EOF_DIRLIST1 BUFF2...” 将简化为:

dfu searc/versio=min=200'excludes'form="!AS"/out=tmp.tmp dka0:

无论有多少文件,这几乎都将在几秒钟内运行。 扔掉整个警告内容,包括它总是检查 32000,因为它(几乎)是免费的。 执行 DFU 命令后,如果 tmp.tmp 不为空,则通过创建标头并附加 tmp.tmp 创建“fancy”输出。总是删除 tmp.tmp ($ CLOSE/DISP=DELETE )

免费咨询...

那些 15 深嵌套的 IF-THEN-ELSE-ENDIF 来接收消息看起来很糟糕(维护) 考虑一个数组查找?! 下面是一个成功的例子:

$! prep for test
$ EL = p1
$ EL_DIAG = "FILE.DAT"
$ LOCAL_STATUS = "12345"
$
$! Code snippet to be tested
$
$ x  = 'EL'
$ ! Fold multiple conditions into 1 message
$
$ if  (EL .EQ. 7) .OR. (EL .EQ. 14) .OR. (EL .EQ. 21) .OR. (EL .EQ. 25) -
                .OR. (EL .EQ. 29) .OR. (EL .EQ. 30)  THEN x = "L1"
$
$ MSG_6     = "error opening "       + EL_DIAG + " for WRITE (RM=" + LOCAL_STATUS + ")"
$ IDT_6     = "OPENIN"
$ MSG_L1    = "error reading from "  + EL_DIAG + " (RM=" + LOCAL_STATUS + ")"
$ IDT_L1    = "READERR"
$ MSG_8     = "device name missing " + EL_DIAG
$ IDT_8     = "DNNF"
$
$ ! Pick up the required texts
$
$ IF F$TYPE(MSG_'x').EQS.""
$ THEN
$   WRITE SYS$OUTPUT "No message found for code: ", EL
$   EXIT 16
$ ENDIF
$
$ MSG   = MSG_'x
$ IDTXT = IDT_'x
$
$ WRITE SYS$OUTPUT "MSG  : ", MSG
$ WRITE SYS$OUTPUT "IDTXT: ", IDTXT

干杯, 海因

【讨论】:

    【解决方案2】:

    两个 cmets 都是一个很好的开始。仔细检查它们。 哪个 OpenVMS 版本?过去 2 年的东西?

    只需抓住并使用 DFU!

    $ define/user sys$output nl:
    $ mcr dfu searc/versio=min=200/excl=(*.dat,*.tmp)/form="!AS"/out=tmp.tmp dka0:
    $ type tmp.tmp
    BUNDY$DKA0:[SYS0.SYSMGR]OPERATOR.LOG;242
    BUNDY$DKA0:[SYS0.SYSMGR]ACME$SERVER.LOG;241
    BUNDY$DKA0:[SYS0.SYSMGR]LAN$ACP.LOG;241
    

    您还可以考虑将 F$SEARCH 放在一个循环中并解析出版本和其他有趣的组件来实现您的排除...。

    $
    $ type SEARCH_HIGH_VERSION.COM
    $ max = 200
    $ old = ""
    $ IF p1.EQS."" THEN EXIT 16 ! PARAM
    $loop:
    $ file = F$SEARC(p1)
    $ IF file.EQS."" THEN EXIT 99018 ! NMF
    $ IF file.EQS.old THEN EXIT 100164 ! Not wild
    $ old = file
    $ version = F$PARSE(file,,,"VERSION") - ";"
    $ IF max.GE.'version' THEN GOTO loop
    $ ! IF ... further string tests
    $ WRITE SYS$OUTPUT file
    $ GOTO LOOP
    $
    $ @SEARCH_HIGH_VERSION.COM *.*;*
    SYS$SYSROOT:[SYSMGR]ACME$SERVER.LOG;241
    SYS$SYSROOT:[SYSMGR]LAN$ACP.LOG;241
    SYS$SYSROOT:[SYSMGR]OPERATOR.LOG;242
    SYS$SYSROOT:[SYSMGR]TMP.TMP;304
    SYS$SYSROOT:[SYSMGR]TMP.TMP;303
    SYS$SYSROOT:[SYSMGR]TMP.TMP;302
    SYS$SYSROOT:[SYSMGR]TMP.TMP;301
    SYS$SYSROOT:[SYSMGR]TMP.TMP;300
    %RMS-E-NMF, no more files found
    $
    $ @SEARCH_HIGH_VERSION.COM tmp.tmp
    SYS$SYSROOT:[SYSMGR]TMP.TMP;304
    %RMS-F-WLD, invalid wildcard operation
    $
    

    DFU 可能比 DIR 快 10* DIR 将比 F$SEARCH 快 10*,但您会在处理过程中失去它。

    祝你好运! 海因

    【讨论】:

    • 注意,您不想为此使用 PERL 通配符,因为它会为每个命中 (stat) 进行文件头访问。 Find::File 不返回(多个)版本。 READDIR 也许是的,但这是工作。这行得通,但正如我所说,它很慢: perl -le "for (){ $v=$1 if /;(\d+)/; next if $v
    • Hein,谢谢你的代码。我在 DIR 命令中添加了一个排除子句。但是,我有一个变量文件,它为主脚本提供节点、设备和限制。我希望能够为每个设备添加排除项(目前它在所有设备上)。从变量文件中收集符号值时,我使用 F$ELEMENT(6, ",", BUFF)。我将如何写从第 7 到行尾的所有内容?目前它只写入下一个,因此只尝试(并且失败)排除第一个列出的文件,而每个设备可能有多个文件。提前感谢您提供的任何东西
    • 嗯,您没有分享足够的详细信息,无法让我们提供帮助。就像一个变量文件的例子。并且磁盘循环通常必须绕过文件循环,可能使用 F$DEVICE 作为 F$SEARCH 和 DFU 一次只能在 1 个设备上工作。诚然,您可以为 DIR 提供一个列表,但这可能不是应该如何使用的。而且……它开始听起来很像工作!乐于提供想法和例子,不乐于做这项工作:-)。
    • Hein,请看下面的 pastebin (pastebin.com/qSxqWaWY),里面有完整的脚本和变量文件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2010-12-03
    相关资源
    最近更新 更多