Here is my implementation (tested, but no guarantee for no bug)
It loops & RegExMatch & shift to next position +> to find all match objects.
; you need to use `O)` in your regex to use match object
; https://www.autohotkey.com/boards/viewtopic.php?t=87233
regexMatchAll(content_SearchOn, regexPatternStr_MatchFor, ind_MatchFromPosition := 1) {
;~ stdout := FileOpen("*", "w")
arr_matcher := []
while (true)
{
ind_RegexGroupAll := RegExMatch(content_SearchOn, regexPatternStr_MatchFor, matcher, ind_MatchFromPosition)
; you cannot use `while (ind_RegexGroupAll != 0)`, cuz its would be evaluated after a Null match already pushed inside the array -> you must `break the loop` soon, before `arr_matcher.Push(matcher)`
if (ind_RegexGroupAll == 0) { ; Zero is returned if the pattern is not found.
break
}
arr_matcher.Push(matcher)
;~ ind_RegexGroupAll_Matcher := matcher.Pos ; Dont use this, if no match, all these `matcher.*` are null
length_RegexGroupAll := matcher.Len
ind_MatchFromPosition := ind_RegexGroupAll + length_RegexGroupAll
;~ stdout.WriteLine("ind_RegexGroupAll: " . ind_RegexGroupAll)
;~ stdout.WriteLine("ind_RegexGroupAll_Matcher: " . ind_RegexGroupAll_Matcher)
;~ stdout.WriteLine("length_RegexGroupAll: " . length_RegexGroupAll)
;~ stdout.WriteLine("ind_MatchFromPosition: " . ind_MatchFromPosition)
if (length_RegexGroupAll == 0) { ; avoid zero-width match
ind_MatchFromPosition += 1
if (ind_MatchFromPosition > StrLen(content_SearchOn)) { ; avoid `ind_MatchFromPosition += 1` leads to out of bound -> inf loop (this happens if a zero-width match is at the end of `content_SearchOn`)
; @performance `StrLen(content_SearchOn)` can be improved
break
}
}
}
return arr_matcher
}
; ;test; ; >>>>> Run Code Test
; ;test; content_SearchOn =
; ;test; (
; ;test; Mode 1 (default): Specify a variable in which to store the part of Haystack that matched the entire pattern. If the pattern is not found (that is, if the function returns 0), this variable and all array elements below are made blank.
; ;test;
; ;test; If any capturing subpatterns are present inside NeedleRegEx, their matches are stored in a pseudo-array whose base name is OutputVar. For example, if the variable's name is Match, the substring that matches the first subpattern would be stored in Match1, the second would be stored in Match2, and so on. The exception to this is named subpatterns: they are stored by name instead of number. For example, the substring that matches the named subpattern (?P<Year>\d{4}) would be stored in MatchYear. If a particular subpattern does not match anything (or if the function returns zero), the corresponding variable is made blank.
; ;test;
; ;test; Within a function, to create a pseudo-array that is global instead of local, declare the base name of the pseudo-array (e.g. Match) as a global variable prior to using it. The converse is true for assume-global functions. However, it is often also necessary to declare each element, due to a common source of confusion.
; ;test; )
; ;test;
; ;test; regexPatternStr_MatchFor := "m`aO)b(.*?) " ; https://www.autohotkey.com/boards/viewtopic.php?t=50537&p=223767
; ;test; arr_matcher := regexMatchAll(content_SearchOn, regexPatternStr_MatchFor)
; ;test;
; ;test; stdout := FileOpen("*", "w")
; ;test; for ind_matcher_curr, matcher_curr in arr_matcher
; ;test; {
; ;test; stdout.WriteLine(ind_matcher_curr . ": " . matcher_curr.Value)
; ;test; }
; ;test;
; ;test; ; >>>>> Output
; ;test; ; >"E:\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "C:\Users\Zlgtx\Desktop\AHK scripts\Test\Test.ahk"
; ;test; ; 1: ble
; ;test; ; 2: ble
; ;test; ; 3: below
; ;test; ; 4: bpatterns
; ;test; ; 5: base
; ;test; ; 6: ble's
; ;test; ; 7: bstring
; ;test; ; 8: bpattern
; ;test; ; 9: be
; ;test; ; 10: be
; ;test; ; 11: bpatterns:
; ;test; ; 12: by
; ;test; ; 13: ber.
; ;test; ; 14: bstring
; ;test; ; 15: bpattern
; ;test; ; 16: be
; ;test; ; 17: bpattern
; ;test; ; 18: ble
; ;test; ; 19: bal
; ;test; ; 20: base
; ;test; ; 21: bal
; ;test; ; 22: ble
; ;test; ; 23: bal
; ;test; ; >Exit code: 0 Time: 0.271