'replace multiple occurences of a pattern in range given by another patterns
I am a regex noob.
I have the following practical riddle: Modifying a G-code for a multi-extruder 3D printer. Two print heads are being activated with T1/T2 lines, while fan speed is controlled by M106 lines with a second parameter giving the speed of the fan. Some machines require the M106 line be attributed with the tool index, some don't. The generator does not emit the tool number for M106, thus the task is to insert the active tool index after M106. For example, the following G-code
T1
M106 255
...
T1
something
M106 255
...
M106 255
...
T1
M106 255
...
T2
M106 123
...
T1
M106 12
M106 12
...
something
T2
M106 40
shall be modified to
T1
M106 T1 255
...
T1
something
M106 T1 255
...
M106 T1 255
...
T1
M106 T1 255
...
T2
M106 T2 123
...
T1
M106 T1 12
M106 T1 12
...
something
T2
M106 T2 40
For blocks of G-code between T1 and end of G-code or up to Tx with x different from 1 (activating a different extruder), T1 shall be inserted between M106 and the trailing number, similarly for T2. Please note that after T1 there may be multiple occurrences of M106 lines up to T2 and all M106 lines shall be adjusted. Also please note that there may be multiple other lines between T1 and the first M106, between the following M106 lines and between the last M106 and first T2.
Is there a way to adjust all the M106 lines with a single regular expression find / replace?
I was trying to combine various non-greedy patterns with negative lookahead, but I failed miserably.
(T1\n)(?:(.*?M106 +)([\d]+))*?(?!\nT1\n)
We are using boost regex engine, which is supposed to follow the Perl / Javascript rules.
Thanks.
Solution 1:[1]
/(T\d)(?:.(?<!M106.))*/gs
This expression captures T\d
(Tx) as a group, then continues capturing everything after Tx leading up to the end of M106
. You can achieve the desired output by using the match replacement parameters $0 $1
which simply adds the contents of the group ($1) to the contents of the full original match ($0) with a space in between.
Single-line option is enabled so that the .
is able to match line breaks.
Here is a link to the expression in Regex101.
EDIT: This will only fix the first instance of M106 after a Tn, which does not fully solve the problem the OP describes.
There is a catch with solving the problem with a single expression. To add Tx following M106 based on context from earlier in a match, you need to be able to rebuild every part of the input text but with an extra Tx in the correct position. Regex can't capture indefinitely many different groups, so capturing and rebuilding the input text between indefinitely many M106's is not possible.
Solution 2:[2]
As pointed out by the OP, the answer I posted was incorrect. I will delete it shortly.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |