Regex context of a find

A question for regex experts, can't find the answer by myself (I looked !)

I have this :
good 0 df
good 1 dfd
good 2 qdqsd
good 3 ggr
bad 4
good 5 mlp
good 6
good 7

and want to get the context of "bad" with only one "good" before and one "good" after:
good 3 ggr
bad 4
good 5

the best I've got is
(?s)(good.{1,12}bad.*?good)

and it's not working because the range {1,12} is not consistent and fails

Thank you very much if you have a solution

this works for me:
\bgood.*\Rbad.*\Rgood.*

1 Like

Thank you so much for taking the time to answer me !
But in fact I simplified too much my input text...sorry
Have you got a working solution for this one ? Thanks !

input text:
good 1 dfd
kjkkjdf

good 2 qdqsd
jkfkjg
skdlsk

good 3 ggrfdfdfd
dfklfd
dfkl
random length
with multiple lines

bad 4 sdjqklj random length
sd4s54 multiple lines

good 5 mlp
sldsklds

good 6
XXX

desired output:
good 3 ggrfdfdfd
dfklfd
dfkl
random length
with multiple lines

bad 4 sdjqklj random length
sd4s54 multiple lines

good

Don't you mean \bgood.\rbad.\rgood?

@ thoffman666
not working with the text : you can test things at https://regex101.com

@JMichaelTX
Thank you for all your posts everywhere in the forum. Without you sharing your knowledge It would have been so much more difficult.

I could not find a regex to do what I wanted...but I found an ugly solution with 3 different regex searches and variables...
Without any mean to capture a lookbehind or to specify a position in a string int the regex search I could not find any other way...

context Macro (v9.0.5)

context.kmmacros (4.1 KB)

There is nothing ugly about your solution.
While we often would like to have a single RegEx to get our desired solution, sometimes it is better, or we have to resort to, using a sequence of RegEx's, like you did.

This is actually a very challenging Regex problem. I thought the lookahead approach would work, but it does not work exactly like I originally thought.

I did finally find a single RegEx solution, but it requires that your source text have ONLY one block of text that is:

good
and then one or more lines

bad
and then one or more lines

good

This RegEx will match the LAST block of text that fits that pattern:
(?s)\bgood(?!.*?good.*?bad).*?\bbad.*?\bgood

For details, see: regex101: build, test, and debug regex
(ignore the first line of source text)

Example Results

1 Like

Brilliant! Thank you very much.
Do you think that for this kind of thing (string manipulations) the regex approach is inferior to applescript or any other language ?

In a word, no.

I think RegEx is one of the most powerful string manipulation tools available, and the great thing is that it works in a variety of applications and languages. I use RegEx a lot in:

  • KM
  • AppleScript
  • JavaScript
1 Like

\r means just the CR character.

\R (available since 10.11) means any line ending (so \r\n, \r or \n (or others)).

See: ICU User Guide | ICU Documentation

Thanks. I guess that explains why https://regexr.com/ didn't know it.