Inserting 2 lines of text 2 lines prior to a known variable
-
I am working on modifying G-code file and I need to enter 2 lines of code 2 lines before a known value.
“M96” is the consistent value:
N149 G02 X50.0063 Y84.3353 I0.8597 J34.9894
N150 G03 X50.2137 Y85.8542 I-6.7013 J1.6885
N151 G260
N152 M96
I need to insert:
M107
FV.E. FEEDRATE[7]
2 Lines before every instance of “M96”
N149 G02 X50.0063 Y84.3353 I0.8597 J34.9894
M107
FV.E.FEEDRATE[7]
N150 G03 X50.2137 Y85.8542 I-6.7013 J1.6885
N151 G260
N152 M96
I am able to add the text right above M96 by using the below, but I am not sure how to enter it 2 lines prior.
Find What =
M96
Replace With =\n\M107\n\FV.E.FEEDRATE[7]\n\M96
Search Mode = REGULAR EXPRESSION
Dot Matches Newline =NOT CHECKED -
There are multiple ways of doing it.
One is to use a “lookahead” that matches two whole lines followed by a line containing
M96
. Because it’s a lookahead, the “cursor” is still at the beginning of the first of those three lines, so any replacement you do will be before those three lines, so 2 lines before theM96
:
FIND =(?-s)(?=^.*$\R.*$\R.*M96\b)
REPLACE =M107\nFV.E.FEEDRATE[7]\n
SEARCH MODE = regular expression
(the(?-s)
will cause the regex to be equivalent to .-matches-newline not checked whether or not it’s checked)
(Because the cursor was at the start of the line two lines before M96, I put the newlines at the end of each line in the replacement)Note that I used the Unix LF
\n
for the newline in the replacement, which is what you showed (though I was confused by the extra\
between your\n
and yourM107
in the replacement). If you really have Windows CRLF newlines, use\r\n
for each newline in the replacement.You could also do a non-lookahead match which stores the previous two lines through the M96 in a capture group, or makes use of the
$0
“whole capture” group:
FIND =(?-s)^.*$\R.*$\R.*M96\b
REPLACE =M107\nFV.E.FEEDRATE[7]\n$0
SEARCH MODE = Regular Expression----
Useful References
-
@peterjones Thank you! I appreciate it!
-
Hello @daniel-James, @peterjones and All,
The regex S/R, provided by @peterjones, supposes that you click ONCE only on the
Replace All
buttonIndeed, given this INPUT text :
N149 G02 X50.0063 Y84.3353 I0.8597 J34.9894 N150 G03 X50.2137 Y85.8542 I-6.7013 J1.6885 N151 G260 N152 M96 N153 G04 X50.0063 Y84.3353 I0.8597 J34.9894 N154 G05 X50.2137 Y85.8542 I-6.7013 J1.6885 N155 G870 N156 M96
Assuming that the
Wrap around
is tickedAnd the following regex S/R :
SEARCH
(?-si)(?=^.+\R.+\R.+M96\b)
REPLACE
M107\nFV.E. FEEDRATE[7]\n
If you click, for instance, three times on the
Replace All
button, you’ll get the following OUTPUT text :N149 G02 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] M107 FV.E. FEEDRATE[7] M107 FV.E. FEEDRATE[7] N150 G03 X50.2137 Y85.8542 I-6.7013 J1.6885 N151 G260 N152 M96 N153 G04 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] M107 FV.E. FEEDRATE[7] M107 FV.E. FEEDRATE[7] N154 G05 X50.2137 Y85.8542 I-6.7013 J1.6885 N155 G870 N156 M96
Not exactly what we want, isn’t it ?
We can solve this problem by using backtracking control verbs. The idea is to use the couple
(*SKIP)(*FAIL)
or(*SKIP)(*F)
with the generic regex :What I DON’T want
(*SKIP)(*F)|
What I DO wantThis leads to the practical regex S/R :
SEARCH
(?-si)^M107\R(?:.+\R){3}.+M96\b(*SKIP)(*F)|(?=^.+\R.+\R.+M96\b)
REPLACE
M107\nFV.E. FEEDRATE[7]\n
Note that the part to discard, before
(*SKIP)
, is the five complete lines beginning withM107
and ending withM96
So, given the INPUT text, below, containing two sections where the two lines
M107...FV.E...
have already being inserted :N149 G02 X50.0063 Y84.3353 I0.8597 J34.9894 N150 G03 X50.2137 Y85.8542 I-6.7013 J1.6885 N151 G260 N152 M96 N153 G05 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N154 G06 X50.2137 Y85.8542 I-6.7013 J1.6885 N155 G500 N156 M96 N157 G07 X50.0063 Y84.3353 I0.8597 J34.9894 N158 G08 X50.2137 Y85.8542 I-6.7013 J1.6885 N159 G100 N160 M96 N161 G00 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N162 G99 X50.2137 Y85.8542 I-6.7013 J1.6885 N163 G300 N164 M96 N165 G10 X50.0063 Y84.3353 I0.8597 J34.9894 N166 G20 X50.2137 Y85.8542 I-6.7013 J1.6885 N167 G000 N168 M96
The new regex S/R would give, after a first click on the
Replace All
button :N149 G02 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N150 G03 X50.2137 Y85.8542 I-6.7013 J1.6885 N151 G260 N152 M96 N153 G05 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N154 G06 X50.2137 Y85.8542 I-6.7013 J1.6885 N155 G500 N156 M96 N157 G07 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N158 G08 X50.2137 Y85.8542 I-6.7013 J1.6885 N159 G100 N160 M96 N161 G00 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N162 G99 X50.2137 Y85.8542 I-6.7013 J1.6885 N163 G300 N164 M96 N165 G10 X50.0063 Y84.3353 I0.8597 J34.9894 M107 FV.E. FEEDRATE[7] N166 G20 X50.2137 Y85.8542 I-6.7013 J1.6885 N167 G000 N168 M96
And, as expected, all the subsequent clicks, on the
Replace All
button, would return the messageReplace All: O occurrences were replaced
!
If we do not want to use the uncommon
(*...)
syntaxes, a solution, with a conditional replacement, could be :SEARCH
(?-si)(^M107\R(?:.+\R){3}.+M96\b)|(?=^.+\R.+\R.+M96\b)
REPLACE
?1$0:M107\nFV.E. FEEDRATE[7]\n
However, with this solution, and assuming our second INPUT text, we get :
-
Five replacements after a first click on the
Replace All
button ( Twoidentical
replacements and threeinsertions
) -
Five
identical
replacements after any subsequent click on theReplace All
button
Best Regards,
guy038
-
-
@guy038 said in Inserting 2 lines of text 2 lines prior to a known variable:
What I DON’T want(*SKIP)(*F)|What I DO want
THAT is a nice way to put it. :-)
-
Hi, @alan-kilborn, and All,
Actually, I was inspired by this article :
https://www.rexegg.com/backtracking-control-verbs.html#skipfail
where it is said :
In effect,
(*SKIP)(*FAIL)
says: “Throw away anything you can match to the left of me.”
Please, visit this excellent regex site :
BR
guy038