Hey, is it possible to search right to left using RegExMatch? I know it can be done with InStr() by setting starting position to 0, but was wondering about RegEx.
Thanks.
Is there a RegExMatch option to search right to left?
Re: Is there a RegExMatch option to search right to left?
You can use $ to anchor the regular expression to the end of the text (or to the end of a line if it is used in conjunction with the m option).
If you need a more specific example post a sample haystack and needle desired match.
Code: Select all
Test := "abc1abc2abc3"
RegExMatch(Test, "abc\d$", m)
MsgBox, % m
Re: Is there a RegExMatch option to search right to left?
Not correct, see posts below.
Like this? Pattern "a.*?$" search the first "a" from left to right.
Key: use $ to fix left boundary, and ? makes quantifiers *+?{} ungreedy.
Like this? Pattern "a.*?$" search the first "a" from left to right.
Key: use $ to fix left boundary, and ? makes quantifiers *+?{} ungreedy.
Last edited by RobertL on 12 Sep 2014, 02:07, edited 1 time in total.
我为人人,人人为己?
Re: Is there a RegExMatch option to search right to left?
PCRE (and therefore RegExMatch and RegExReplace) does not support searching right-to-left.
kon: Anchoring to the end will let you find a substring at the end of the haystack. It will not let you search right-to-left.
RobertL: It finds the first "a" from left to right, as you say. That's exactly the opposite of what the OP is asking for.
Making * ungreedy does not help. It will still begin the match at the first 'a' (left to right) it sees and will not try alternative 'a's if the first one matches.
For finding the last match, you can usually use greedy .*:
\K excludes the part matched by .* from the final result.
A negative look-ahead assertion will usually also work:(?1) is used to avoid repeating the pattern. It refers to the (a) part of the pattern.
kon: Anchoring to the end will let you find a substring at the end of the haystack. It will not let you search right-to-left.
RobertL: It finds the first "a" from left to right, as you say. That's exactly the opposite of what the OP is asking for.
Making * ungreedy does not help. It will still begin the match at the first 'a' (left to right) it sees and will not try alternative 'a's if the first one matches.
Code: Select all
MsgBox % RegExMatch("b a b a b", "a") ; 3
MsgBox % RegExMatch("b a b a b", "a.*?$") ; 3
MsgBox % RegExMatch("b a b a b", "a.*$") ; 3
Code: Select all
MsgBox % RegExMatch("b a b a b", ".*\Ka")
A negative look-ahead assertion will usually also work:
Code: Select all
MsgBox % RegExMatch("b a b a b", "(a)(?!.*(?1))")
Re: Is there a RegExMatch option to search right to left?
Aha, I find could use \K almost the same time~
Also, thanks for negative look-ahead with back references method.
Also, thanks for negative look-ahead with back references method.
我为人人,人人为己?
Re: Is there a RegExMatch option to search right to left?
Code: Select all
h:="a b c d fffffffffaffffffffafffffd"
n=a
loop, % strlen(h)
if pos := RegExMatch(A_index=1?h:SubStr(h,1,strlen(h)-StrLen(n)*A_Index),n,m,strlen(h)-StrLen(n)*A_Index)
MsgBox % " found ``" m "`` at position " pos
Re: Is there a RegExMatch option to search right to left?
Code: Select all
RegExMatch("b a b a b", "O).*(a)",o)
MsgBox % o.Pos[1] ;7
我为人人,人人为己?
Re: Is there a RegExMatch option to search right to left?
I remember one idea for this was to turnaround both the haystack and needles accordingly.
Code: Select all
Test := "abc1abc2abc3"
Loop, Parse, Test
out := A_LoopField out
MsgBox % out
RegExMatch(out, "\dcba", m)
MsgBox, % m
Re: Is there a RegExMatch option to search right to left?
Aha, turnaround both the haystack and needles accordingly would be confused and disoriented, especially writing pattern.
Wait, could it deal with "b a b a b", to find the first "b" from left? Remember to turnaround the position of result..
Wait, could it deal with "b a b a b", to find the first "b" from left? Remember to turnaround the position of result..
Code: Select all
haystack:="b a b a b"
MsgBox % StrLen(haystack) - RegExMatch(haystack, ".*?a") -1 ;7
;Use "Once-only subpatterns" (in some case, I'm not sure):
MsgBox % StrLen(haystack) - RegExMatch(haystack, "(?>.*a)") ;7
Last edited by RobertL on 16 Sep 2014, 08:16, edited 1 time in total.
我为人人,人人为己?
Re: Is there a RegExMatch option to search right to left?
This should work.
Code: Select all
h:="a65 b c d ff1ff3fffabcffaffff12ffffafabcabcb12cd"
n:="\d\d"
;h:="b a b a b"
;n:="b"
loop
if pos := RegExMatch(a_Index=1?h:SubStr(h,1,pos?pos:strlen(h)),n,m,strlen(h)-A_Index)
{
if (strlen(h)-A_Index)<0
break
if (pos_old!=pos)
{
pos_old:=pos
MsgBox % "Found ``" m "`` at position " pos "`nLenght: " strlen(h)
}
}
Re: Is there a RegExMatch option to search right to left?
You could match everything and then pull out the result you want. Here are my takes:
...or the in-line version (but unlike the one above, it doesn't give you the positions):
For reverse order, you would just iterate from x.MaxIndex() to 1 or retrieve x[x.MaxIndex()-n], where x is the array of results.
Edit: Fixed .+? bug
Code: Select all
h:="a65 b c d ff1ff3fffabcffaffff12ffffafabcabcb12cd"
n:="\d\d"
s := ""
for i,m in RegExMatchAll(h, n)
s .= i "=" m.0 "`n"
MsgBox % s
RegExMatchAll(str, pat, pos := 1)
{
static matches
if IsObject(str) ; Callout mode
{
matches.Insert(str)
return
}
RegExMatch(pat, "sO)(^[^\(]*\))?(.*)", pat)
opt := pat.1 != "" ? pat.1 : ")"
pat := "O" opt "(?:" pat.2 ")(?C" A_ThisFunc ")"
matches := [], RegExReplace(str, pat, "",,, pos)
return matches
}
Code: Select all
h:="a65 b c d ff1ff3fffabcffaffff12ffffafabcabcb12cd"
n:="\d\d"
s := ""
for i,m in StrSplit(Trim(RegExReplace(h, "s).*?(" n "|$)", (d:=Chr(31)) "$1"), d), d)
s .= i "=" m "`n"
MsgBox % s
Edit: Fixed .+? bug
Re: Is there a RegExMatch option to search right to left?
With starting position.
Code: Select all
h:="a65 b c d ff1ff3fffabcffaffff12ffffafabcabcb12cd664429123443"
;n:="\w\w"
;n:="[a-z]\d"
;n:="65"
n:="\d\d\d\d"
pos := RevExMatch(h,n,m,"a",allm,59)
;pos := RevExMatch(h,n,m,"a",allm)
MsgBox % "last matched position: " pos "`nlast matched: " m "`nall matches: " allm "`nhaystack length: " strlen(h)
ExitApp
RevExMatch(h,n, ByRef ma:="", r:="1", ByRef f="",p:="",d:=",") { ;RevegxMatch() returns the position of the last match starting from the end of the haystack, h=haystack, n=needle, r=2 returns the 2nd match (m) (r=a=all last match), f= store all the matches delimited by d="," p=start position
if (r="a" or r="all")
r:=strlen(h)
else if r is space
r=1
else if r is not digit
r=1
if p is space
p:=StrLen(h)
else if p is not digit
p:=StrLen(h)
else if (p>strlen(h))
p:=StrLen(h)-p
tmp:=0, h2:=h, h:=SubStr(h,1,p)
loop
{
if ((strlen(h2)-A_Index )<0)
return lp
if pos := RegExMatch(h,n,m,p)
{
h:=SubStr(h,1,pos-1), p-=StrLen(m), tmp++, f .= tmp=1?m:d m, lp:=pos, ma:=m
If (r=tmp)
return lp
}
else
p--
}
}
Re: Is there a RegExMatch option to search right to left?
Wow, what a nice design RegExMatchAll and the in-line version is, from lexikos.
A little bug in the in-line version, "s).+?(" n "|$)" should be "s).*?(" n "|$)", otherwise would miss "12" in "12a34".
Collection and summaries with this topic in Chinese: 正则-匹配模式的所有实例, 正则反向查找.
A little bug in the in-line version, "s).+?(" n "|$)" should be "s).*?(" n "|$)", otherwise would miss "12" in "12a34".
Collection and summaries with this topic in Chinese: 正则-匹配模式的所有实例, 正则反向查找.
我为人人,人人为己?
Re: Is there a RegExMatch option to search right to left?
A function can do it, no need for RegEx
Code: Select all
RInStr(Haystack, Needle, CaseSensitive = false, StartingPos = 1, Occurrence = 1) {
Loop, Parse, Haystack
nHay := A_LoopField . nHay
Loop, Parse, Needle
nNdl := A_LoopField . nNdl
Pos := InStr(nHay, nNdl, CaseSensitive, StartingPos, Occurrence)
If (Pos> 0)
Return 2 + StrLen(Haystack) - Pos - StrLen(Needle)
Else
Return 0
}
Who is online
Users browsing this forum: Google [Bot], Rohwedder and 345 guests