0

Please bear with me, I'm not well versed with Pattern, Matcher or Regex.

I found the below on https://regex101.com/

  1. South African passport: [A|D|M|T][0-9]{8}
  2. South African Id: (([0-9]{2})(0|1)([0-9])([0-3])([0-9]))([ ]?)(([0-9]{4})([ ]?)([0-1][8]([ ]?)[0-9]))
  3. Salesforce CS: (?i)^c\\s\\-\\s\\d{8}

I combined them into: [A|D|M|T][0-9]{8}|(([0-9]{2})(0|1)([0-9])([0-3])([0-9]))([ ]?)(([0-9]{4})([ ]?)([0-1][8]([ ]?)[0-9]))|(?i)^c\\s\\-\\s\\d{8} and it works on the regex101 website but it doesn't work in Apex.

I know regex works differently in Apex but I'm not exactly sure what to change.

  • Sample South African Id: 9202204720082
  • Sample South African Passport: A01524783
  • Case Number: C - 12246503

Here's my method in Apex:

public String findMatch(
    String text,
    String regex
) {
    Matcher emailMatcher = Pattern.compile(regex).matcher(text);
    return (emailMatcher.find()) ? emailMatcher.group() : '';
}

What do I need to change to make it work? Any help is appreciated.

1 Answer 1

3

The main problem is likely the ^; in the default mode or DOTALL (single-line mode), this character can only match the very beginning of the string (i.e. the place before the very first character), while in multiline mode, it can match at that spot, and also any place immediately after a newline (\r or \n).

In other words, this won't match:

String s = 'Hello.\nYour case number is:\nC - 12246503';

Because the default match mode isn't multiline mode.

Either remove the ^, or add the multiline mode flag (e.g. (?im) for case-insensitive multiline mode).

Because of the limitations of regex in Apex, you would do well to optimize your pattern. Here's my revised suggestion, assuming you didn't mean the ^:

[ADMT]\\d{8}|\\d{2}[01]\\d[0-3]\\d ?\\d{4} ?[01]8 ?\\d|(?i)C - \\d{8}

[A|D|M|T] actually matches A, D, M, T, and |. [] is a character class, so matches everything inside (with some exceptions). We fix it with [ADMT].

[0-9] has a shorthand notation, \\d.

(0|1) can be written as [01].

([ ]?) can be simply ?.

[8] is just 8.

\\s is used for all manner of whitespace (depending on the DOTALL mode), but you probably only need the space character .

Note that compiling takes time, so you should use some sort of cache in your code:

static Map<String, Pattern> patterns = new Map<String, Pattern>();

public String findMatch(
    String text,
    String regex
) {
    Pattern thePattern = patterns.get(regex);
    if(thePattern == null) {
        // Assignment and placing the value in the map
        patterns.put(regex, thePattern = Pattern.compile(regex));
    }
    Matcher emailMatcher = thePattern.matcher(text);
    return thePattern.find()? thePattern.group() : '';
}
1
  • Insightful! Thank you for the detailed response @sfdcfox
    – d_k
    Commented Mar 23, 2023 at 17:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .