Page 1 of 1

Negation in multiline regex?

Posted: 05 May 2021, 15:09
by kunkel321
My goal is to have a list like below, then one regex will find a sub-list that contains everything except not the lines that end with "-Opts]." Then, another regex will find only those lines that do end with it. Normally the caret ^ negates things. The Regex Quick Guide in the docs say that it doesn't work when the m) option is used though... So how do I hide those lines?

Also, just what does that caret (circumflex?) do in the below conditions?! If I run the script as show below, I get all 9 lines returned in %myVar%. But if I remove the caret, then only lines 1-7 are returned... Strange--yes?

Code: Select all

#NoEnv ; For security
#SingleInstance force
#Persistent

Haystack =
(
[1 PWN Consent for Initial EVAL]
[2 PWN Consent for Initial EVAL-Opts]
[3 PWN--Transfer]
[4 PWN--Transfer-Opts]
[5 PWN Need to do TRIennial REEVAL]
[6 PWN Need to do TRIennial REEVAL-Opts]
[7 PWN EARLY REEVAL REMOVE areas]
[8 PWN MDR -- NOT manifestation]
[9 PWN MDR -- IS manifestation]
)

Needle := "m)\[\N+[^-Opts]\]"

RegExMatch(Haystack, Needle, myVar) 
MsgBox Found:`n`n %myVar% 
return

Re: Negation in multiline regex?  Topic is solved

Posted: 05 May 2021, 15:36
by Smile_
Not one regex

Code: Select all

Haystack =
(
[1 PWN Consent for Initial EVAL]
[2 PWN Consent for Initial EVAL-Opts]
[3 PWN--Transfer]
[4 PWN--Transfer-Opts]
[5 PWN Need to do TRIennial REEVAL]
[6 PWN Need to do TRIennial REEVAL-Opts]
[7 PWN EARLY REEVAL REMOVE areas]
[8 PWN MDR -- NOT manifestation]
[9 PWN MDR -- IS manifestation]
)

Result := ""
Loop, Parse, Haystack, `n, `r
If !(A_LoopField ~= "\Q-Opts]\E$")
    Result .= A_LoopField "`n"
Msgbox % Result

Result := ""
Loop, Parse, Haystack, `n, `r
If (A_LoopField ~= "\Q-Opts]\E$")
    Result .= A_LoopField "`n"
Msgbox % Result
Edit:
Replaced RegExMatch(A_LoopField, "\Q-Opts]\E$") with (A_LoopField ~= "\Q-Opts]\E$") (~= operator requires [v1.0.90+])

Re: Negation in multiline regex?

Posted: 05 May 2021, 16:23
by kunkel321
Beautiful! Many thanks Smile_!

Re: Negation in multiline regex?

Posted: 05 May 2021, 16:30
by boiler
@kunkel321 - The group [^-Opts] is not saying “do not match -Opts” because a group of characters in brackets means match any character within this group. When you put the ^ at the start of it, it means match any character not contained in this group. So [^-Opts] is actually saying match any character other than -, O, p, t, or s.

Re: Negation in multiline regex?

Posted: 05 May 2021, 16:41
by mikeyww
This is not better or worse. OK, maybe it actually is worse (and might not always work)!

Code: Select all

str =
(
[1 PWN Consent for Initial EVAL]
[2 PWN Consent for Initial EVAL-Opts]
[3 PWN--Transfer]
[4 PWN--Transfer-Opts]
[5 PWN Need to do TRIennial REEVAL]
[6 PWN Need to do TRIennial REEVAL-Opts]
[7 PWN EARLY REEVAL REMOVE areas]
[8 PWN MDR -- NOT manifestation]
[9 PWN MDR -- IS manifestation]
)
SendInput % RegExReplace(str, "\V+-Opts]\n")
Send `n`n
SendInput % Trim(RegExReplace("`n" str "`n", "(\A|-Opts])\n\K\[.+?]\n(?=(\[.+?-Opts]|\Z))"), "`n")

Re: Negation in multiline regex?

Posted: 05 May 2021, 17:03
by teadrinker
mikeyww wrote:

Code: Select all

RegExReplace(str, "\V+-Opts]\n")
Try:

Code: Select all

str =
(
[10 PWN Need to do TRIennial REEVAL-Opts]
)
Better RegExReplace(Haystack, "\V*-Opts]\R?")

Re: Negation in multiline regex?

Posted: 05 May 2021, 17:09
by mikeyww
Great point, of course!

You proved me right when I claimed to be wrong....

Re: Negation in multiline regex?

Posted: 06 May 2021, 12:57
by kunkel321
Thank you everyone, for the feedback!

-Smile, I think you might have broken yours when you took the RegExMatch out. It was working before, but maybe not now(??)

-Re the negation character: Now I'm wondering how you would do "not -Opts" Maybe with the caret on the outside?? ^[-Opts]

Re: Negation in multiline regex?

Posted: 06 May 2021, 13:14
by boiler
kunkel321 wrote: -Re the negation character: Now I'm wondering how you would do "not -Opts" Maybe with the caret on the outside?? ^[-Opts]
No, because outside of the brackets, the ^ tells it to anchor it to the beginning of the haystack, and the stuff in the brackets is still just a group of characters, so it would match any single character in that group.

Depending on how and where you want to match (or not match), there are various "negative" matching groups that say don't match this string, such as (?!-Opts).

Re: Negation in multiline regex?

Posted: 06 May 2021, 13:21
by Smile_
@kunkel321
Screenshot.png
RegMatch
Screenshot.png (11.14 KiB) Viewed 617 times
It is supposed to be a shorthand of RegExMatch() but yeah it needs [v1.0.90+] as documented, I missed that sorry, then just put the old option or update the Auto-Hotkey version.
For me it works.

Re: Negation in multiline regex?

Posted: 06 May 2021, 13:32
by teadrinker
kunkel321 wrote: how you would do "not -Opts"

Code: Select all

str =
(
[1 PWN Consent for Initial EVAL]
[2 PWN Consent for Initial EVAL-Opts]
[3 PWN--Transfer]
[4 PWN--Transfer-Opts]
[5 PWN Need to do TRIennial REEVAL]
[6 PWN Need to do TRIennial REEVAL-Opts]
[7 PWN EARLY REEVAL REMOVE areas]
[8 PWN MDR -- NOT manifestation]
[9 PWN MDR -- IS manifestation]
)
MsgBox, % RegExReplace(str, "m`a)^(?!\V*-Opts]$)\V*\R?")

Re: Negation in multiline regex?

Posted: 07 May 2021, 10:43
by kunkel321
@Smile_: I guess you're right... I just tried your above code again and it did work. I'm not sure what I did wrong last time...

Mikeyww and Teadrinker, I'm still trying to digest your patterns! LOL. I'm actually not new to regexes, though it might seem like I am from this thread. :mrgreen:

New related question: I see that Teadrinker has used \V in a couple spots. The docs indicate that this is a "vertical tab." Is that how it is used here?

Re: Negation in multiline regex?

Posted: 07 May 2021, 11:04
by boiler
kunkel321 wrote: New related question: I see that Teadrinker has used \V in a couple spots. The docs indicate that this is a "vertical tab." Is that how it is used here?
The docs do not indicate that. They indicate that it matches a character that is not a vertical whitespace character. You apparently are referrring to \v. It's similar to how \s matches a whitespace character and \S matches any non-whitespace character.

Re: Negation in multiline regex?

Posted: 07 May 2021, 11:11
by mikeyww
Very true.

@teadrinker has a better version than mine, so would have a look at that one.

Re: Negation in multiline regex?

Posted: 07 May 2021, 17:15
by kunkel321
boiler wrote:
07 May 2021, 11:04
The docs do not indicate that. They indicate that it matches a character that is not a vertical whitespace character. You apparently are referrring to \v. It's similar to how \s matches a whitespace character and \S matches any non-whitespace character.
Yea, my bad. I think I accidentally typed a forward slash into the 'find' box and found this (which isn't even part of a pattern) at the very bottom of the table that shows the different options.
`a [v1.0.46.06+]: `a recognizes any type of newline, namely `r, `n, `r`n, `v/VT/vertical tab/chr(0xB), `f/FF/formfeed/chr(0xC), and NEL/next-line/chr(0x85). [v1.0.47.05+]: Newlines can be restricted to only CR, LF, and CRLF by instead specifying (*ANYCRLF) in uppercase at the beginning of the pattern (after the options); e.g. im)(*ANYCRLF)^abc$.