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.