2

I want to check if specific word appears before another word? If it appears it must not match, if doesn't appear it must match, there can be other words between them

Here is example string: My name is Jack Brown

I want to check if name word appears before Jack, here is my regex:

regex: (?<!name)\b(Jack)\b

but untortunately it works only when there is no any words between them, can someone help?

kakajan
  • 2,614
  • 2
  • 22
  • 39

4 Answers4

1

You need to negate the name before Jack.

(?=^(?:(?!name).)*Jack.*$).*

Short Explanation

  • (?:(?!name).)* Anything except the word name
  • Jack.* Exact word Jack and other optional characters
  • .* Match the whole string if assertions are true

Python Example

import re

s1 = "My name is Jack Brown"
s2 = "I am Jack Brown"

def doesMatch(string):
    return bool(re.search(r"(?=^(?:(?!name).)*Jack.*$).*", string))

print(doesMatch(s1))  # False
print(doesMatch(s2))  # True

Also, see the regex demo

Artyom Vancyan
  • 5,029
  • 3
  • 12
  • 34
  • 1
    thanks for reply, this regex will accept the other variations of Jack too, ex: `My name is Jacky Chan`, but I need to match specific words, so I think handle it by boundaring word `Jack`, regex: `(?=^(?:(?!name).)*\bJack\b.*$).*` – kakajan Aug 07 '22 at 12:02
  • Sure it is also a solution. My answer is about negating the `name` with `(?:(?!name).)*` – Artyom Vancyan Aug 07 '22 at 12:04
  • One more question, can we check if word `name` appears any where? After Jack or before Jack, does not matter, if word `name` is in string, it must return False, can you help for it? – kakajan Aug 07 '22 at 12:06
  • Then you can use [`(?=^(?:(?!name).)*$).*`](https://regex101.com/r/V87x7B/1) to negate the `name` in the whole string. – Artyom Vancyan Aug 07 '22 at 12:08
1

If you want to disallow full word name before matching full word Jack then this regex will be much more efficient (take note of number of steps on regex101 site):

^(?:Jack\b|(?=\w+(?: +(?!name\b)\w+)* +Jack\b)).*

This regex uses alternation to either:

  • Match Jack at the start OR
  • Match Jack before matching 1+ words if that word is not full word name.

RegEx Demo 1

Now if you want to disallow full word name anywhere in the line i.e before or after then use:

^(?!.*\bname\b).*\bJack\b.*

RegEx Demo 2

anubhava
  • 761,203
  • 64
  • 569
  • 643
1

One can avoid regex and just use string index method.

s = 'My name is Jack Brown'
s.index('name') < s.index('Jack')
True

If one needs regex, the same indexing idea could be used as follows:

def check_string(s,name='nam', Jack='Jac'):
    try: 
        return re.search(rf'\b{name}.*?\b', s).start() < re.search(rf'\b{Jack}.*?\b', s).start()
    except Exception as e:
        return False

s = 'My is Jack Brown'
check_string(s)
False
s = 'My name is Jack Brown'
check_string(s)
True
LetzerWille
  • 5,355
  • 4
  • 23
  • 26
  • Good idea but this way it's not possible to take word boundaries into account. – bobble bubble Aug 07 '22 at 17:36
  • 1
    @bobblebubble. You are correct. I have added lines with the re.search which does also allow to compare indexes. Now one can use the word boundaries with this approach. – LetzerWille Aug 07 '22 at 19:35
0

To check if there is no name before Jack how about

^\W*(?:(?!name\b)\w+\W+)*?Jack.*

Here is a demo at regex101

This pattern checks if none of the words before jack is name by use of a negative lookahead.
\w matches a word character and upper \W the negation of it (non word characters).

bobble bubble
  • 16,888
  • 3
  • 27
  • 46