find the closest word to another word from right to left Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
rj8810
Posts: 31
Joined: 16 Jul 2018, 22:34

find the closest word to another word from right to left

Post by rj8810 » 22 Jul 2022, 18:36

I think the clearest and most summarized way to express what I want to achieve is the following:
find the nearest word(yellow) to another word(blue) from right to left
example:
yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow....

finding the nearest word (red) to another word (blue) from left to right is so easy using ".*?" ..... I'm surprised it's so hard from right to left:

Code: Select all

RegExMatch("yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow...", "blue.*?red", m)
MsgBox, % m ; bluexxxred1
I want the coincidence to be: yellow1xxxbluexxxred1

any help thank you very much in advance nice community

User avatar
mikeyww
Posts: 27121
Joined: 09 Sep 2014, 18:38

Re: find the closest word to another word from right to left

Post by mikeyww » 22 Jul 2022, 18:57

This post should be simple, but I'm confused by it. Suggestion: provide the exact input string, the exact output string, the definition of a word, and any other relevant examples.

sofista
Posts: 652
Joined: 24 Feb 2020, 13:59
Location: Buenos Aires

Re: find the closest word to another word from right to left  Topic is solved

Post by sofista » 23 Jul 2022, 10:42

rj8810 wrote:
22 Jul 2022, 18:36
I think the clearest and most summarized way to express what I want to achieve is the following:
find the nearest word(yellow) to another word(blue) from right to left
example:
yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow....

finding the nearest word (red) to another word (blue) from left to right is so easy using ".*?" ..... I'm surprised it's so hard from right to left:

Code: Select all

RegExMatch("yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow...", "blue.*?red", m)
MsgBox, % m ; bluexxxred1
I want the coincidence to be: yellow1xxxbluexxxred1

any help thank you very much in advance nice community
It is not so difficult to accomplish that, but, as mikeyww and I apparently see it, the problem is that it is not as clearly defined as you state.

As I understand it, I would describe the issue as follows: in the exact order stipulated, find the word "yellow" followed by one more characters that do not include the word yellow (1), followed by the word "blue", continued by one or more characters (2) and ended by the word "red" (3).

Some potential problems:

1) The regular expression example uses the symbol "*" - quantifier for more than one or none - but the example string indicates that there are characters, so "+" would be the more appropriate symbol.
2) Same as above. Another issue is that it is not excluded that the word "yellow" may appear between "blue" and "red".
3) It is not indicated whether the characters following the word "red" are relevant or not. It is also not indicated whether the three words are on the same line or whether a multi-line search is required.

Now, ignoring the last two potential problems, to find only the word "yellow" closest to "blue" and "red" I would do it like this:

Code: Select all

str := "yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow...."
RegExMatch(str, "yellow(?:(?!yellow).)*?blue.*?red1", m)
MsgBox, % m    ; yellow1xxxbluexxxred1
Tested.

rj8810
Posts: 31
Joined: 16 Jul 2018, 22:34

Re: find the closest word to another word from right to left

Post by rj8810 » 07 Aug 2022, 00:39

sofista wrote:
23 Jul 2022, 10:42

It is not so difficult to accomplish that, but, as mikeyww and I apparently see it, the problem is that it is not as clearly defined as you state.

As I understand it, I would describe the issue as follows: in the exact order stipulated, find the word "yellow" followed by one more characters that do not include the word yellow (1), followed by the word "blue", continued by one or more characters (2) and ended by the word "red" (3).

Some potential problems:

1) The regular expression example uses the symbol "*" - quantifier for more than one or none - but the example string indicates that there are characters, so "+" would be the more appropriate symbol.
2) Same as above. Another issue is that it is not excluded that the word "yellow" may appear between "blue" and "red".
3) It is not indicated whether the characters following the word "red" are relevant or not. It is also not indicated whether the three words are on the same line or whether a multi-line search is required.

Now, ignoring the last two potential problems, to find only the word "yellow" closest to "blue" and "red" I would do it like this:

Code: Select all

str := "yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow...."
RegExMatch(str, "yellow(?:(?!yellow).)*?blue.*?red1", m)
MsgBox, % m    ; yellow1xxxbluexxxred1
Tested.
thank you very much, :lol: :bravo: :thumbup:
you saw my approach from another approach also successful.
Your code perfectly fulfills my purpose in all the scenarios in which I have tried it.
it always happens to me the same, sometimes for a period, comma, or an exclamation mark I end up reading 7 days in a row, in this case it was for two parenthesis and a period, although I don't remember having seen something similar to your code in the ahk documentation.

Code: Select all

q::
str := "yellow3xxxyellow2xxxyellow1xxxbluexxxred1xxxred2xxxred3xxxyellow....againt...yellow2xxxblue2xxxred2...againt...yellow3xxxblue3xxxred3"

p := 1
array := []
while p:= RegExMatch(str, "yellow(?:(?!yellow).)*?blue.*?red", m, p+StrLen(m))
{
Array[A_Index] := m 
msgbox % "Element number " . A_Index . " is " . Array[A_Index]
Count := Array.Count()
}
msgbox, % "count =" Count
return
and it also works in my real scenario: html documents

Code: Select all

q::
content = notvalifirstdhref="validfirsthref="/item/mykeyword-iid-1111111">second href="/item/mykeyword-iid-2222222">
keyword:="mykeyword"
search = href="(?:(?!href=).)*?%keyword%.*?">


p := 1
array := []

while p:= RegExMatch(content, search, m, p+StrLen(m))
{
	Array[A_Index] := m ;esto sólo recupera el subpatron
MsgBox, % m
Count := Array.Count()
}
msgbox, % "count =" Count

return

La única forma que encuentro para agradecerte es también compartiendo, si esto te puede ser útil o tienes mejores ideas, te invito a ver este post, con el cual logré mi propósito completo: web scraping con regexmatch en la nube con autohotkey.ahk
viewtopic.php?f=76&t=107135
tema completo: "cómo hacer que las teclas de acceso rápido automático funcionen en la PC a través de conexiones rdp, o que funcionen en escritorios virtuales múltiples, diferentes e independientes sin que los scripts interfieran entre sí".
sometimes I think that ahk in the cloud is the future.
And I definitely learned that approaching an issue from different points of view has a higher chance of success and you get different ways to solve it.
I previously posted a topic asking how to prevent a negative look-ahead (?!....) or negative look-behind (?<!...) from searching the whole string and only taking effect up to a certain word, in this case "red1", since these codes didn't work.

Code: Select all

q::
MsgBox % RegExMatch("xxxxyellow222xxxyellow111yyyyblueñññred111xxxred222againstyellow...", "yellow(?<!.*yellow).*?blue.*?red", SsubPat)

MsgBox, %SsubPat% ; show yellowyyyyblueñññred
return

ñ::
MsgBox % RegExMatch("xxxxyellow222xxxyellow111yyyyblueñññred111xxxred222againstyellow...", "yellow(?!.*yellow).*?blue.*?red", SsubPat)

MsgBox, %SsubPat% ; show yellowyyyyblueñññred

but the forum got too long...
and you solved it and gave me the exact answer on the first try with a yellow(?:(?!yellow).), looking at it from your approach.
finally thanks

see you next time friends...

sofista
Posts: 652
Joined: 24 Feb 2020, 13:59
Location: Buenos Aires

Re: find the closest word to another word from right to left

Post by sofista » 08 Aug 2022, 08:02

@rj8810 Glad my regex worked, even in the real cases. BTW, if you need any explanation of how the regular expression works, just ask.

Regarding the linked script, the collaboration is appreciated, and I hope it will be used.

Saludos y hasta la próxima :)

Post Reply

Return to “Ask for Help (v1)”