Regex code to detect all matches before specific text

Viewed 52

I need a regex which will only analyze part of the text. In the following example, I need to find matches before the word CONFIDENTIAL

So in this text:

this is some text for john@domainA.com
this is some text for mary@domainB.com where also pat@domainc.com is copied
CONFIDENTIAL 
this is some text for john@domainA.com
this is some text for mary@domainB.com where also pat@domainc.com is copied

The expression should only match the first 3 email address. I tried with something like:

[A-Za-z0-9]{2,30}(@domainA.com|@domainB.com|@domainC.com)(?=CONFIDENTIAL)

But that yields NO match, where as

[A-Za-z0-9]{2,30}(@domainA.com|@domainB.com|@domainC.com)

Matches all emails, I have been playing in this notepad in regex101.com.

https://regex101.com/r/iNpprH/2

Is what I am requesting possible just using regexp?

2 Answers

You need to actually allow any char before CONFIDENTIAL:

[A-Za-z0-9]{2,30}@(?:domainA\.com|domainB\.com|domainC\.com)(?=[\w\W]*?CONFIDENTIAL)

Or,

(?s)[A-Za-z0-9]{2,30}@(?:domainA\.com|domainB\.com|domainC\.com)(?=.*?CONFIDENTIAL)

See the regex demo. Note I moved @ outside of the grouping since it will be present in any of the matches, and I escaped literal dots.

Details

  • [A-Za-z0-9]{2,30} - two to thirty alphanumeric chars
  • @ - a @ char
  • (?:domainA\.com|domainB\.com|domainC\.com) - the alternatives with domains with TLDs
  • (?=[\w\W]*?CONFIDENTIAL) - here, note that [\w\W]*? matches any chars, 0 or more occurrences but as few as possible, and then CONFIDENTIAL. Since it is a lookahead, the text will only be checked for a match, but won't get consumed.

The following regular expression (with flags gmi set) matches email addresses that appear before the word "CONFIDENTIAL".

(?:\A|\G)(?:(?!\bCONFIDENTIAL\b)[A-Z\d\s])*?\K[A-Z]+@[A-Z]+\.[A-Z]+\b

Start your engine!

The problem is complicated by the fact that there is no assurance that CONFIDENTIAL appears only once in the string.

For convenience I've assumed that each of the three parts of email addresses consists of one or more letters. Both the permitted characters and limits on length can be changed as needed.

The regex engine performs the following operations.

(?:                    : begin a non-capture group
  \A                   : match beginning of string (not line)
  |                    : or
  \G                   : assert position at the end of the previous match
                         or the start of the string for the first match
)                      : end non-capture group
(?:                    : begin a non-capture group
  (?!\bCONFIDENTIAL\b) : the current match is not followed by
                         CONFIDENTIAL 
  [A-Z\d\s]            : match one char in the char class
)                      : end non-capture class
*?                     : execute the non-capture class 0+ times, lazily
\K                     : forget everything matched so far and
                         reset the beginning of the match
[A-Z]+                 : match 1+ letters
@[A-Z]+\.[A-Z]+\b      : match '@', 1+ letters, '.', 1+ letters

(?:(?!\bCONFIDENTIAL\b)[A-Z\d\s]) is called a tempered greedy token.

Related