【问题标题】:Regex to match the last line of a JCL job card or the whole card正则表达式匹配 JCL 工作卡的最后一行或整张卡
【发布时间】:2022-01-15 12:41:27
【问题描述】:

如果你们中有人熟悉大型机 JCL。
我正在尝试匹配工作卡的最后一行。

基本上第一行以// 开头并没有逗号结束。 在示例中,我需要匹配第 3 行或最多第 3 行。

我正在使用 Ansible 的 lineinfile 在工作卡之后动态插入路线卡。

例如:

//SPOOL1   JOB (UU999999999,1103),'Programmer',CLASS=0, <--- start of job card
//         REGION=0M,MSGCLASS=R,TIME=5, LINES=(999999,WARNING),
//         NOTIFY=&SYSUID  <--- end of job card
//STEPNAME EXEC PGM=BPXBATCH 
//STDERR   DD   SYSOUT=*
//STDOUT   DD   SYSOUT=*
//STDPARM  DD   *
SH cat /dev/urandom

到目前为止,我得到了这个,它与 // 的开头和之后的任何内容相匹配,但是,我无法弄清楚最后一部分

^(\Q//\E(.)*)

【问题讨论】:

  • JOB卡总是以//SPOOL开头吗?还是被//XXX JOB识别?
  • @Bohemian SPOOL1 是用户定义的工作名称:mainframestechhelp.com/tutorials/jcl/job-card.htm
  • 您是否需要担心第 73 - 80 列中的行号或其他问题?您必须说明工作卡最后一行以逗号结尾的注释吗?
  • @Mr.White 不一定正确:基本上第一行以 // 开头,不带逗号。 您可以将带引号的参数继续到下一行。您对开场报价进行编码,键入最多 pos 的文本。 71. 续行以 // 开头,后跟空格,直到 pos 15。然后参数文本继续以 pos 开头。 16. 有一行以逗号结尾的 // not 开头,但仍然不是 JOB 语句的最后一行。 (删除并添加了评论,但更正了拼写错误。)

标签: regex parsing ansible mainframe jcl


【解决方案1】:

您可以为此使用negative lookbehind(?&lt;!,)
但是您还需要在firstmatch 之后插入并使用backrefs

给定任务:

- lineinfile:
    path: file.jcl
    regexp: '^(\/\/.*)(?<!,)$'
    line: "\\1\\n//*ROUTE statement"
    firstmatch: true
    backrefs: true

根据您的示例,您最终会得到:

//SPOOL1   JOB (UU999999999,1103),'Programmer',CLASS=0,
//         REGION=0M,MSGCLASS=R,TIME=5, LINES=(999999,WARNING),
//         NOTIFY=&SYSUID
//*ROUTE statement
//STEPNAME EXEC PGM=BPXBATCH 
//STDERR   DD   SYSOUT=*
//STDOUT   DD   SYSOUT=*
//STDPARM  DD   *
SH cat /dev/urandom

【讨论】:

    【解决方案2】:

    匹配整个工作卡(在本例中为 3 行):

    (?sm)\A.*?\/\/[^*]((?!\/\*)[^\n])*[^,]$
    

    live demo

    分解:

    • (?sm)
      • s 启用 DOTALL 标志(意思是 . 也匹配新行)
      • m 启用 MUTLILINE 标志(意思是 ^$ 匹配行的开头和结尾
    • \A 表示输入的开始(所以它只匹配最开始)
    • .*? 意味着任何东西,但越少越好
    • //[^*]
    • ((?!\/\*)[^\n])* 表示非新行,除了序列/* (所以当注释放入行时不匹配)
    • [^,] 不是逗号
    • $ 行尾

    英文:“从头开始匹配,直到行尾的非逗号不是注释,或不以注释结尾”

    然后您将替换为 $0(第零组是整个匹配项),然后是您注入的内容:

    $0\\n*ROUTE statement
    

    【讨论】:

    • 感谢现场演示链接。我的正则表达式不够好,无法质疑您的答案,但 rubular.com 上的快速测试表明它不能可靠地工作。请注意,在 JCL 中,注释可能会出现在空格后的每一行。如果我在第一行添加这样的注释,则正则表达式仅匹配第一行。
    • @phunsoft 正则表达式调整为处理注释行。也可以查看新的演示。
    • 仍然不处理注释在行尾的情况。不完整和简化的规则是:JCL 中的每条记录(行)都以 pos 中的// 开头。 1,最多有四个字段由一个或多个空格分隔。如果 pos.3 是*,那么整行都是注释。如果不是*,而是非空白,则为 name 字段(最多 8 个字符)。单个单词操作字段,例如JOBDD,跟在名称后面(如果没有名称,则为空白)。可变长度参数字段遵循操作。当最后一个字符为 not , 时识别出 parameters 结束,否则在下一行继续。 comment 字段遵循 parameters
    • (续) JCL 是一头丑陋的野兽。还有更多奇特的规则使解析变得不平凡。
    • @phunsoft 正则表达式现在处理行尾的注释。现在链接到 python 正则表达式测试器,因为 ansible 使用 python 正则表达式引擎。
    【解决方案3】:

    对于一般情况,这比您想象的要困难,因为在 JOB 卡范围内允许使用 cmets。

        //SPOOL1   JOB (UU999999999,1103),'Programmer',CLASS=0, <--- start of job card
        //         REGION=0M,MSGCLASS=R,TIME=5, LINES=(999999,WARNING),
        //         NOTIFY=&SYSUID  <--- end of job card
    

    你显示的字符串:

    • LINES=(999999,WARNING),

    在 JCL 中作为 cmets 都是有效的,因为它们跟在空格后面。

    您甚至可以在 JOB 卡中包含完整的注释行。例如:

    //name    JOB (accounting info),'data capture ___',     
    //*            TYPRUN=SCAN,                                               
    //             NOTIFY=&SYSUID,                                            
    //             CLASS=A,MSGCLASS=T,MSGLEVEL=(1,1),TIME=(5,00),             
    //             REGION=5M  
    

    因此,除非您可以限制您正在查看的 JCL,否则您不一定要寻找第一张不以逗号结尾的卡片。

    您的工作卡以//name JOB 开头,并在下一张//name 卡之前结束。 *** 编辑 *** 正如正确指出的那样,JOB 卡后面可以跟着一张不需要名称字段的卡,例如 // SET。见https://www.ibm.com/docs/en/zos/2.4.0?topic=statements-jcl-statement-fields***编辑结束***

    它以 ^(\Q//\E)[A-Z0-9]+\s+\QJOB\E.+ 开头 并在下一张命名牌之前结束 ^(\Q//\E)[A-Z0-9]+\s+

    但我不太了解正则表达式,无法找到插入新行的“之前”点。希望其他人可以添加。

    【讨论】:

    • 不完全正确:您的 JOB 卡以 //name JOB 开头,并在下一张 //name JOB 之前结束。name 在所有 JCL 语句中都是可选的,JOB 语句除外。例如。在SET 语句中通常没有名字;不需要它,因为您无法引用它。
    【解决方案4】:

    在一般情况下解析 JCL 是困难。正如 cmets 所述,规则充满了警告。

    我有一个 ANTLR4 grammar for JCL,它是 MIT 许可的。 可能有用。它体现了JCL的美丽。

    【讨论】:

    • 你是男人...
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    相关资源
    最近更新 更多