‘(*MARK:NAME)’ for RegEx Match.Mark Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 03:47

The RegExMatch doc says
Match.Mark: Returns the NAME of the last encountered (*MARK:NAME), when applicable.
Is (*MARK:NAME) documented anywhere?


[Mod action: Moved topic to the v1 section since the v2 version was abandoned later in the thread and a full v2 script was never posted.]
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 04:49

To be more specific: It's straightforward that (*MARK:NAME) is a text to be inserted in the NeedleRegEx. But I'm missing further details. In particular: Can that be only used for complete matches? For example in the following code:

Code: Select all

iPos := RegExMatch("<a hello> <b world> <x !>",  "OsiU)"
	. "(*MARK:0)<a (?P<Alpha>.+)>.*"
	. "(*MARK:1)<b (?P<Bravo>.+)>.*"
	. "(*MARK:2)<c (?P<Charlie>.+)>.*"
	. "(*MARK:3)"
	, o)
MsgBox "Mark=‘" o.Mark "’"
, I would like to get the value 2, since it matched everything up to c.
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 05:29

Like this?

Code: Select all

str := "<a hello> <b world> <c !>"
needle := "O)(*MARK:0)<a (?P<Alpha>.+?)> (*MARK:1)<b (?P<Bravo>.+?)> <c (*MARK:2)(?P<Charlie>.+?)>"
iPos := RegExMatch(str,  needle, out)
MsgBox % out.Mark
Last edited by andymbody on 06 Sep 2023, 06:03, edited 1 time in total.
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 05:58

With non-capturing subpatterns (?:)|(?:alternative) around each row one can achieve that only the marks of matches are exposed. But there are two problems with that:
  • It's quite intricate to devise the alternative for each row.
  • If the last case (Charlie) matches, it will just return c, so that the script doesn't know if any earlier case failed.
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:04

andymbody wrote:
06 Sep 2023, 05:29
I could be wrong, but I think your needle is gibberish (not formatted correctly).
What specifically would you like to extract from the string "<a hello> <b world> <x !>"
I think the needle is well formatted, but it expects a different haystack, namely the same with "c" instead of "x". That is just here for demonstration what happens if the script gets a non-matching haystack. With "c", the MsgBox correctly returns 3.
Last edited by Micromegas on 06 Sep 2023, 06:06, edited 1 time in total.
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:05

I edited my last post after you posted a reply...

This return "2" as requested. Does this work?

Code: Select all

str := "<a hello> <b world> <c !>"
needle := "O)(*MARK:0)<a (?P<Alpha>.+?)> (*MARK:1)<b (?P<Bravo>.+?)> <c (*MARK:2)(?P<Charlie>.+?)>"
iPos := RegExMatch(str,  needle, out)
MsgBox % "Mark='" . out.Mark . "'"
I've never seen this "Mark" feature used... thx for the post, I learned something...
Andy
Last edited by andymbody on 06 Sep 2023, 06:14, edited 1 time in total.
User avatar
boiler
Posts: 17143
Joined: 21 Dec 2014, 02:44

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:13

@andymbody — This is the v2 section. You posted v1 code in reply.
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:15

andymbody wrote:
06 Sep 2023, 06:05
This return "2" as requested. Does this work?
No. It simply returns 2 because you left out the mark 3. It still returns nothing if there is no match for Charlie.
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:17

boiler wrote:
06 Sep 2023, 06:13
@andymbody — This is the v2 section. You posted v1 code in reply.
Yes, but it's only one character change: Just leave out the %.
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:24

boiler wrote:
06 Sep 2023, 06:13
@andymbody — This is the v2 section. You posted v1 code in reply.
oops!
Micromegas wrote:
06 Sep 2023, 06:15
No. It simply returns 2 because you left out the mark 3. It still returns nothing if there is no match for Charlie.
I see... now I understand the delima... but can't try other things right now... gotta get to work. Best of luck!
User avatar
boiler
Posts: 17143
Joined: 21 Dec 2014, 02:44

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 06:28

Micromegas wrote: Yes, but it's only one character change: Just leave out the %.
You would also need a & preceding the output variable in the RegExMatch call, which your original script also needed.
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 07:53

This may be obvious, but I think the reason it does not show '2' is because the match fails in it's entirety. In other words, Alpha and Bravo fail as well, when the entire string is not matched. This begs the question... what is the "Mark" feature good for if the entire string must match as well?

Does this sound accurate?
User avatar
boiler
Posts: 17143
Joined: 21 Dec 2014, 02:44

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 08:15

It apparently will be set when there is an error in executing the RegEx, not a successful execution that resulted in no match. See the PERl RegEx documentation.
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 08:18

andymbody wrote:
06 Sep 2023, 07:53
Does this sound accurate?
Yes, thanks. I also agree that the condition that the whole string must match reduces the usefulness of the "Mark" feature. But i can still imagine some limited use in a case like this:

Code: Select all

needle := "(?:a(*MARK:found_a))|(?:[^a.](*MARK:found_something_else))"
Call_Match("....a...", needle)
Call_Match("....x...", needle)

Call_Match(haystack, needle) {
	RegExMatch(haystack, needle, &o)
	MsgBox  "haystack=‘" haystack "’`nMark=‘" o.Mark "’"	
}
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 08:25

is this helpful at all (it is in v1, sorry). It makes the a b or c optional.

This returns 1 because 1 is associated with Bravo and is the last valid match

Code: Select all

str := "<a hello> <b world> <x !> goodbye"
needle := "O)"
	. "(?:(*MARK:0)<a (?P<Alpha>.+?)>)*"	. "\h*"		; optional Alpha, followed by optional horz spaces
	. "(?:(*MARK:1)<b (?P<Bravo>.+?)>)*"	. "\h*"		; optional Bravo, followed by optional horz spaces
	. "(?:(*MARK:2)<c (?P<Charlie>.+?)>)*"	. ".*"		; optional Charlie, followed by optional misc chars
iPos := RegExMatch(str,  needle, out)
MsgBox % out.mark
ExitApp
UPDATE:
Unfortunately the above code returns 0 for this haystack.
str := "<a hello> <x world> <c !> goodbye" ; returns 0
So it seems that once the match fails the first time (whether the others are optional or not) it does not continue any further checks. Which makes sense, but is probably not very helpful. The good news is... it does return something rather than "invalid entire match" which was happening before.
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 10:14

andymbody wrote:
06 Sep 2023, 08:25
[…] once the match fails the first time […] it does not continue any further checks.
This seems related to my second bullet of 2:58 am. You showed that what I wrote then was too narrow: One can tweak the needle so that a different subpattern fails first. But what i need is simply the mark for the failed subpattern. (Well, the first in case there are more than 1, but that's not the point here. For this question, we can simply assume there is just 1). It seems there's no way to write a needle for that.

Different question: Since we're discussing v.1.1, should we move the question to the board for that?
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 10:43

Micromegas wrote:
06 Sep 2023, 10:14
...what i need is simply the mark for the failed subpattern
Is using multi needles and testing for each separately, a possibility, or out of the question?

Or maybe addition/nested grouping?
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 11:15

andymbody wrote:
06 Sep 2023, 10:43
Is using multi needles and testing for each separately, a possibility, or out of the question?
That's what i'm considering. It's extra work and a performance drain, of course, but it should get the job done.
andymbody wrote:
06 Sep 2023, 10:43
Or maybe addition/nested grouping?
Haven't thought of that. By the latter, you mean nested non-capturing subpatterns? Wouldn't they have the same problem? And what do you mean by ‘addition’?
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 11:17

boiler wrote:
06 Sep 2023, 08:15
See the PERl RegEx documentation.
You mean https://perldoc.perl.org/perlre#Special-Backtracking-Control-Verbs? I will look into that, thanks!
User avatar
andymbody
Posts: 927
Joined: 02 Jul 2017, 23:47

Re: ‘(*MARK:NAME)’ for RegEx Match.Mark

06 Sep 2023, 11:35

Micromegas wrote:
06 Sep 2023, 11:15
Do you mean nested non-capturing subpatterns? Wouldn't they have the same problem? And what do you mean by ‘addition’?
Lol... I got an idea that seemed correct briefly in my head, but in practice didn't work. And it became very complex just trying to keep it all straight. So... scratch that garbage thought.

The separate checks and processing afterwards is a possibility tho. I don't have any real world data that you are checking for but each check returns much more data to work with. You could then build up the substrings to return the actual failed positions. There is probably an easier way that some of these guy can provide in 3 lines of code. But I haven't found that yet.

I'm not able to concentrate fully tho... since my job gets in the way... don't you just hate when that happens? :lol:

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: CuriousDad, Google [Bot] and 93 guests