Home > front end >  Regex to match the last line of a JCL job card or the whole card
Regex to match the last line of a JCL job card or the whole card

Time:12-11

If any of you are familiar with mainframe JCL.
I'm trying to match the last line of the job card.

Basically the first line that starts with // and ends without a comma. In the example I need the 3rd line or up to the 3rd line matched.

I'm using Ansible's lineinfile to dynamically insert a route card after the job card.

For example:

//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

So far I got this, which matches the start of // and anything after, but, I cant figure out the last part

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

CodePudding user response:

You can use a negative lookbehind for this: (?<!,).
But you'll also need to insert after the firstmatch and use backrefs.

Given the task:

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

You would end up, from your example, with:

//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

CodePudding user response:

To match the whole job card (in this case 3 lines):

(?s)\A.*?[^,]$

See live demo.

Breaking this down:

  • (?s) enables the DOTALL flag
  • \A means start of input (so it only matches at the very start)
  • .*? means anything, but as little as possible
  • [^,] not a comma
  • $ end of line

In English: "match from the start until there's a non-comma at the end of a line"

You would then replace with $0 (group zero is the entire match) followed by your injected content:

$0\\n*ROUTE statement

CodePudding user response:

For the general case this is tougher than you think because of comments allowed within the scope of the JOB card.

    //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

The strings you show:

  • <--- start of job card
  • LINES=(999999,WARNING),
  • <--- end of job card

are all valid as comments in JCL because they follow a space.

You can even have whole comment lines within the JOB card. For example:

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

So you're not necessarily looking for the first card that doesn't end in a comma unless you can restrict the JCL you're looking at.

Your JOB card starts with //name JOB and ends just before the next //name card.

It starts with ^(\Q//\E)[A-Z0-9] \s \QJOB\E. and ends just before the next named card ^(\Q//\E)[A-Z0-9] \s

But I don't know regular expressions well enough to find the "just before" point to insert your new line. Hopefully someone else can add that.

  • Related