1

I want to match and expression that contains the string yes, but only if it's not preceded by the string no.

For example, this with match: Hello world, major yes here!
But this will not match: Hell no yes

The second string does not match because the yes string is preceded by no string. Apparently this needs negated lookbehind, which is not implemented in JavaScript regex flavor, I've tried stuff like that: /((?!no ))yes/
/^(?!.*no) yes$/

but they don't seem to have the desired effect :/

MeLight
  • 5,136
  • 2
  • 35
  • 61

3 Answers3

3

You could try the below regex.

^(?=(?:(?!\bno\b).)*yes).*

DEMO

Explanation:

^                        the beginning of the string
(?=                      look ahead to see if there is:
  (?:                      group, but do not capture (0 or more
                           times):
    (?!                      look ahead to see if there is not:
      \b                       the boundary between a word char
                               (\w) and something that is not a
                               word char
      no                       'no'
      \b                       the boundary between a word char
                               (\w) and something that is not a
                               word char
    )                        end of look-ahead
    .                        any character except \n
  )*                       end of grouping
  yes                      'yes'
)                        end of look-ahead
.*                       any character except \n (0 or more times)
Avinash Raj
  • 160,498
  • 22
  • 182
  • 229
2

I don't think there is a need of regex here. You can just do it like this

var str = "Hell no yes", match = null, no = str.indexOf("no"), yes = str.indexOf("yes");
if(no >= 0 && (yes < 0 || no < yes)) { // check that no doesn't exist before yes
   match = str.match(/yes/)[0]; // then match the "yes"
}
Amit Joki
  • 53,955
  • 7
  • 67
  • 89
  • +1 for using simple code and not a messy regex hack. May have to make sure the "no" comes right before the "yes" though. – jfriend00 Oct 19 '14 at 17:34
  • That's a wonderful solution, but to another problem. I have an array of regexes for different situations - which are more complex than this one. And I don't want to implement flow logic for every string case I might have - that's what regexes were invented for. – MeLight Oct 19 '14 at 17:37
  • @MeLight - so just make a function that you pass two words to and you can reuse the same code everywhere. – jfriend00 Oct 19 '14 at 17:40
  • @jfriend00 what if I need three words? Or G-d forbid numbers? That's going to be a pretty messy function... – MeLight Oct 19 '14 at 17:41
  • 1
    @MeLight then you'll really have to create a messier regex and quite complex too – Amit Joki Oct 19 '14 at 17:42
  • So basically your collective advice is not to use regular expression for string matching? – MeLight Oct 19 '14 at 17:43
  • 1
    This statement fails if `str` doesn't contains `no` (`indexOf() = -1`). So it need extra condition – hindmost Oct 19 '14 at 17:43
  • @MeLight - my advice is to not use messy complicated regexes unless you and all people who will ever work on your code are regex whizzes. Regex is wonderfully powerful, but complicated regexes are insanely obtuse and unclear and very difficult to debug when a few lines of code can often make the code very simple to understand. You didn't pose a limitless set of arbitrary string matching problems. You posed one string matching problem to which Amit provided an answer. – jfriend00 Oct 19 '14 at 17:45
  • Great, but I've mentioned I needed a JavaScript regex also... Why not providing me with a Python solution which will also work? Because that's not what I asked. – MeLight Oct 19 '14 at 17:46
  • @hindmost added. Thanks! – Amit Joki Oct 19 '14 at 17:47
  • @MeLight then, let my answer be helpful for other users who might not be interested in regex, and as far as helping you, I thought you will be interested, but don't mind as you got the answer which you expected :) – Amit Joki Oct 19 '14 at 17:49
  • @Amit Joki That's not a good fix/solution. Use this instead: `var i1 = str.indexOf('yes'), i2 = str.indexOf('no'); var match = i1 >= 0 && (i2 < 0 || i1 < i2);` – hindmost Oct 19 '14 at 17:51
  • Hey, this flow logic thing works out great, doesnt it? – MeLight Oct 19 '14 at 17:51
  • @hindmost thanks. To be honest, I'm feeling dizzy about `>` and ` – Amit Joki Oct 19 '14 at 18:01
1

This should work for you:

var reg = /^((?!no).)*yes.*$/

console.log("Test some no and yes".match(reg))
console.log("Test some yes".match(reg))
console.log("Test some yes and no".match(reg))

Just note that it wont work in sentences where there is no "yes" word like this:

console.log("Test some without".match(reg))

Here is reference that might help more about problem:

Regular expression to match string not containing a word?

Community
  • 1
  • 1
DRAX
  • 24,047
  • 2
  • 21
  • 27