Home > Enterprise >  Match first and last "yes" as well as all "no"
Match first and last "yes" as well as all "no"

Time:10-09

I need PCRE2 regex to find all occurences of "no" as well as first and last occurences of "yes".

Expected results:

"no/yes" - expect two matches: "no" and "yes"
"no/yes/word/yes/no" - expect four matches: "no", "yes", "yes", "no"
"yes/yes/no/word/yes" - expect three matches: first "yes", "no", third "yes"
"yes/no/yes/yes" - expect three matches: first "yes", "no", third "yes"

I try this regex but it don't work as expected with "yes/no/yes/yes".

This subtask can make me happy with main goal.

CodePudding user response:

You are overthinking it.
There is no real point in using ONE regex to replace them all.
Just use multiple regexes.


s.replace(/yes/, ' ').replace(/yes(?!.*yes)/, ' ').replaceAll(/no/g, '-')

Also, there's no real way to replace one entry exept replacing it

CodePudding user response:

You can achieve your desired result, if you can use PCRE2 replacement string conditionals. You can use this regex (whitespace added for clarity, either use the x flag or delete the newlines between alternations):

(no)|
(yes)(?!.*yes)|
((?!(?=(?<a>[\s\S]*))(?<b>yes.*(?=\k<a>\z)|(?<=(?=x^|(?&b))[\s\S])))yes)

It matches one of:

  • (no) : no (captured in group 1)
  • (yes)(?!.*yes) : yes not followed by yes (captured in group 2)
  • ((?!(?=(?<a>[\s\S]*))(?<b>yes.*(?=\k<a>\z)|(?<=(?=x^|(?&b))[\s\S])))yes) : this is the equivalent of a variable length negative lookbehind for (?<!yes.*)(yes) with the yes captured in group 3. For the derivation of this part of the regex, see this blog post.

You can then use conditional replacements, replacing group 1 with - and groups 2 and 3 with

${1: -: }

For input of

no/yes
no/yes/yes/no
/yes/yes/no/yes
no/word/no/yes/yes/yes/no
yes/no
yes/no/yes/word/yes
/word/yes/no/no/no/yes/yes
yes/no/yes/yes

This gives:

-/ 
-/ / /-
/ /yes/-/ 
-/word/-/ /yes/ /-
 /-
 /-/yes/word/ 
/word/ /-/-/-/yes/ 
 /-/yes/ 

Demo on regex101

  • Related