Is this possible with Salesforce's limited regex abilities?
Salesforce's regular expressions are more powerful than people give it credit for. It's just misunderstood because it's different than JavaScript's and Perl's implementations where RegExp has built-in syntax. Java developers would be right at home with Salesforce's regular expressions, as it draws inspiration from Java's Pattern implementation.
In Apex, regular expressions use \
for certain sequences, just as every other language that has regular expressions. However, in Apex, \
is also an escape sequence, so, for example, \b
is BEL (0x07) inside of a string, while \\b
means \b
as far as the regular expression engine is concerned.
Fun fact: BEL is called BEL because in really old computer systems, "printing" a BEL to the screen would cause the computer to beep, which also froze the entire system (including additional output) until the beep finished, which was from an even older technology (teletypewriters), that literally rang a bell when it received this character, in order to get an operator's attention.
So, to get the expected result, you need to double-up on those backslashes. Also, the ||
bit makes it match, well, nothing, so you get spurious matches. It should be just |
:
(?<!\\()\\b(Trazimera|Monoferric)\\b(?![\\w\\s]*[\\)])
Now, as far as getting a list of values, you just need to iterate through each find and group set:
Pattern p = Pattern.compile('(?<!\\()\\b(Trazimera|Monoferric)\\b(?![\\w\\s]*[\\)])');
String s = 'Trastuzumab IV (Herceptin): Request change to Trazimera or Monoferric';
Matcher m = p.matcher(s);
while(m.find()) {
System.debug('Match found: '+m.group(0));
Integer groupCount = m.groupCount() + 1; // 0 is the full match
for(Integer index = 1; index < groupCount; index++) {
System.debug(m.group(index));
}
}
Output:
[5]|DEBUG|Match found: Trazimera
[8]|DEBUG|Trazimera
[5]|DEBUG|Match found: Monoferric
[8]|DEBUG|Monoferric
As you can see, it works just as specified. However, in case it's still not doing what you want, I'd suggest it's your regular expression that's wrong, not Apex.
As far as getting the full list, just add the values to a List. The last element in the List is the last found element.