How can I make this only match the words after the word 'speaks' and ignore commas and spaces

Viewed 72

I have the following RegEX:

/(?<=\w\sspeaks\s)(?!,|\s|\.)([\w]+)/gmi

The string is:

Example Person speaks ExampleLanguage1, ExampleLanguage2, ExampleLanguage3 and ExampleLanguage4.
Example Person two speaks ExampleLanguage1, ExampleLanguage2, ExampleLanguage3 and ExampleLanguage4.
Example Person three speaks ExampleLanguage1 and ExampleLanguage2.

For me, the above only matches:

ExampleLanguage1
ExampleLanguage1
ExampleLanguage1

I want to match:

ExampleLanguage1
ExampleLanguage2
ExampleLanguage3
ExampleLanguage4
ExampleLanguage1
ExampleLanguage2
ExampleLanguage3
ExampleLanguage4
ExampleLanguage1
ExampleLanguage2

The words Example Person can be any word, even without space in-between. And the words ExampleLanguage do not have numbers marked. And they also can have spaces, and can be any word.

Here is a link to it: https://regex101.com/r/MjL8cW/1

3 Answers

If you can make use of the \G anchor, you might match 4 or more word characters, or match words with 1-3 characters and use \K to clear the match buffer.

(?:^.*?\hspeaks|\w{1,3}|\G(?!^))[,.]?\h+\K\w{4,}

The pattern matches:

  • (?: Non capture group
    • ^.*?\hspeaks Match From the start of the string till the first occurrence of a whitespace char and speaks.
    • | Or
    • \w{1,3} Match 1-3 word chars
    • | Or
    • \G(?!^) Assert the position at the end of the previous match, but not at the start
  • ) Close non capture group
  • [,.]?\h+ Match an optional , or . and 1 or more horizontal whitespace chars
  • \K\w{4,} Forget what is matched until so far using \K and match 4 or more word chars

Regex demo

The continue operator seems to be the right thing here. The accepted is fine but there is a problem with 3 letter languages, like Yao, Min, Mon (spoken in Afrika, Asia...)

Try something along this lines:

(?i)(?:speaks\s*\K|(?<!^)\G(?:,|,?\s*and)\s*\K)(?-i)([A-Z](?i)\w+)

Demo

Use

(?<=\bspeaks\b.*?)\b\w{4,}\b

See proof.

Explanation

--------------------------------------------------------------------------------
  (?<=                     look behind to see if there is:
--------------------------------------------------------------------------------
    \b                       the boundary between a word char (\w)
                             and something that is not a word char
--------------------------------------------------------------------------------
    speaks                   'speaks'
--------------------------------------------------------------------------------
    \b                       the boundary between a word char (\w)
                             and something that is not a word char
--------------------------------------------------------------------------------
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
--------------------------------------------------------------------------------
  )                        end of look-behind
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  \w{4,}                   word characters (a-z, A-Z, 0-9, _) (at
                           least 4 times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char

Demo

const string = `Example Person speaks ExampleLanguage1, ExampleLanguage2, ExampleLanguage3 and ExampleLanguage4.
Example Person two speaks ExampleLanguage1, ExampleLanguage2, ExampleLanguage3 and ExampleLanguage4.
Example Person three speaks ExampleLanguage1 and ExampleLanguage2.`
console.log(string.match(/(?<=\bspeaks\b.*?)\b\w{4,}\b/gi))

Related