2

I'm struggling with a "simple" RegEx problem. I wan't to check a sting if the pattern "BN123456" or "bn123456" is included and if so, extract it. The pattern could be in the beginning, middle or end of the string.

So I setup this regex and this test code

Pattern MyPattern = Pattern.compile('[Bb][Nn][0-9]{6}');
Matcher MyMatcher = MyPattern.matcher(' BN123456 bn123456');

System.debug('Match?' + MyMatcher.matches());

while(MyMatcher.find()){
    System.debug('check ' + MyMatcher.group(0));
}

While the RegEx is working on RegEx101 it isn't in the Pattern/Matcher setting. The Problem is, that it finds 'BN123456' only with a space infront ' BN123456'. Any idea why this is the case?

4
  • I would recommend to check in the Stack Overflow forum for RegEx related questions.
    – Arnold Jr.
    Aug 11 at 16:01
  • believe me I did, but honestly I'm struggling finding the right track... but I will also have a look in the helpful link
    – Maserick
    Aug 11 at 16:03
  • 2
    Group zero is always the whole input. Use group(1).
    – Phil W
    Aug 11 at 16:12
  • 2
    @ArnoldJr. This question is about regex nuances using Salesforce-provided regex functionality. OP went through the expected steps (tuning it/testing it on regex101), so it's perfectly fine here, in my opinion.
    – Derek F
    Aug 11 at 16:20

2 Answers 2

5

Your testing code erroneously uses both matches and find. Try the following:

Pattern MyPattern = Pattern.compile('((?:BN|bn)[0-9]{6})');
Matcher MyMatcher = MyPattern.matcher('BN123456 BN');

while(MyMatcher.find()){
    System.debug('check ' + MyMatcher.group(1));
}

System.debug('Done');

(I didn't need to change the pattern, but I thought this was cleaner; @Oleksandr's case insensitive search is even better.)

The point is, there are quite different behaviours for matches and find, and in having applied matches you prevented the subsequent find operations from succeeding. The former, matches:

Attempts to match the entire region against the pattern

but you're interested in a subsequence match which is done by find:

Attempts to find the next subsequence of the input sequence that matches the pattern

These are quotes from the documentation.

1
  • Thank you, this did the trick, matches was only in because I tested things, didn't recognize that this could be the cause of the issue. Thanks!!
    – Maserick
    Aug 11 at 16:26
4

If you want to make this pattern case insensitive, can use (?i) at the beginning of the pattern.

Pattern MyPattern = Pattern.compile('(?i)(BN[0-9]{6})');
Matcher MyMatcher = MyPattern.matcher('1  BN1234561   bn234562.');

while(MyMatcher.find()){
    System.debug(MyMatcher.group());
}

Matcher.matches Attempts to match the entire region against the pattern.

It is not mentioned in apex doc, but mentioned in java doc when it is returning a true:

true if, and only if, the entire region sequence matches this matcher's pattern

that is why in this run, it is returning false

1
  • 1
    (?i)(BN\\d{6}) would also do the trick. Perhaps not a great improvement in this case, but when using posix character classes like \\p{Alnum} or \\p{Graph} it can be clearer (compared to, say, [A-Za-z0-9.,<>/?+-_=]).
    – Derek F
    Aug 11 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.