Can you perform a math function on a RegExReplace backreference before replacing?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Can you perform a math function on a RegExReplace backreference before replacing?

31 Aug 2019, 01:23

@lexikos Thanks for the correction, I've added a "Not recommend" warning in my previous reply.
just me
Posts: 9530
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Can you perform a math function on a RegExReplace backreference before replacing?

31 Aug 2019, 10:07

I don't think this has any advantage over the RegExMatch() approach, but if we have to use a global variable anyway, it might be more reliable not to use this variable inside the RegExReplace():

Code: Select all

#NoEnv
String := "G00G90X1.2Y3.4F14.M8(WAS F14.)`nG01G90X2.2Y3.4F19.6005(WAS F19.6005)`nG84G90X2.2Y3.4F14.00(WAS F14.00)`nG0G91G28Z0`n"
Percentage := 140
Result := ""
RegExReplace(String, "`nm)^[^F]+F(\d+\.?\d*).*$(?C:OverRide)")
MsgBox, %Result%
ExitApp

OverRide(M) {
   Global Percentage, Result
   R := ""
   If InStr(M, "G84")
      R := M
   Else {
      L := StrLen(M1)
      P := InStr(M1, ".")
      Decimals := (P ? (P = L ? 1 : L - P) : 2)
      O := Round(M1 * Percentage / 100, Decimals)
      R := StrReplace(M, "F" . M1, "F" . O, , 1)
   }
   Result .= (R <> "" ? (Result <> "" ? "`n" : "") . R : "")
   Return 0
}
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Can you perform a math function on a RegExReplace backreference before replacing?

31 Aug 2019, 10:48

Test this:

Code: Select all

setbatchlines -1
loop := 10000
loop % loop
   var .= A_Index

a := a_tickcount
VarSetCapacity(r, 16)
RegExReplace(var, "\d(?C:Match)", r)
msgbox % a_tickcount - a

a := a_tickcount
loop % loop
{
   RegExMatch(var, "\d", match)
   Random, r, 10545530, 99453649
   var := RegExReplace(var, match, r,,1,1)
}
msgbox % a_tickcount - a

Match()
{
   global
   Random, r, 10545530, 99453649
   r .= ""
}
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Can you perform a math function on a RegExReplace backreference before replacing?

31 Aug 2019, 13:53

initial testing was successful, but no problems is more important to me than speed, I will be using the looped RegExMatch method for now on code that runs on really expensive machines... Thanks for pointing out the risk and I'm intrigued by everyone's input on solutions to this (also intrigued by regex which I've used but never understood before, now I'm understanding!)

any improvements to my current test case criteria, in either methodology or regex improvements, would be very welcome:

Code: Select all

;find all feedrates and "override" them, test case 140% feed
;avoid modifying comments, stuff within ()s
;don't change the feedrate for tapping cycles, those with G84 and G74
;maintain the same number of decimal places as the original feedrate
;maintain the decimal point or not for integers

String =
(
G1G90X1.F10.M8(WAS F10.)
F10
F10.
F10.0
F10.00
F10.000
X2. Y3. F12.3456 (WAS F12.3456)
G84     F10.00   (TAPPING F10.00)
G1G90X1.F10.F2.34  (WAS F10.F2.34)
G1G90X1.F10  (WAS F10)
X1.F10F10.F10.0F10.00
F10.
(COMMENT)
(FEED)
(F10.0)
)


MsgBox, % RegExReplaceF(string, "O)([^\r\n]*?)F([\-\d.]+(?![^\(]*\)))", Func("Override").Bind(140))


Override(percent, match) {
	if InStr(match.1, "G84") OR InStr(match.1, "G74")
		return match.0
	else
		return match.1 "F" Round(match.2 * percent/100, _:=DecimalPlaces(match.2)) . ((_=0) && InStr(match.2, ".") ? "." : "")
}



DecimalPlaces(n) {
 if (!RegExMatch(n, "^\d*\.(\d*)$", m))
        return 0
    return StrLen(m1)
}


RegExReplaceF(ByRef Haystack, NeedleRegEx, FunctionName, ByRef OutputVarCount := "", Limit := -1, StartingPosition := 1) {
	VarSetCapacity(out, StrLen(Haystack) * (A_IsUnicode+1))
	OutputVarCount := 0
	while ( pos := RegExMatch(Haystack, NeedleRegEx, match, StartingPosition) )
	{
		out .= SubStr(Haystack, StartingPosition, pos-StartingPosition)
		out .= %FunctionName%(match)
		len := IsObject(match) ? match.Len : StrLen(match)
		StartingPosition := pos + len
		if (++OutputVarCount = Limit)
			break
	}
	return out . SubStr(Haystack, StartingPosition)
}



edit: fixed a decimal-point-with-no-places bug, an idiosyncrasy of fanuc style g-code, parameter controlled “pocket calculator style input mode”, by default X10 does not equal X10.
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 177 guests