4

In IDEs a common operation is to perform a search and replace operation using a regex pattern in the search field and another pattern with capture groups in the replacement field.

For example, I can search for (\d)(\D)(\d) and replace it with first: \1; second: \2; third: \3. This would produce the following results.

  • "1a2" => "first: 1; second: a; third: 2"
  • "8o8" => "first: 8; second: o; third: 8"

Is there an easy way to perform this same operation on a String object in Apex? I'm looking for a solution that isn't hard-constrained to only process three capture groups. The number of capture groups is variable: could be 2, 3, 5 or any number.

2 Answers 2

2

There are Matcher and Pattern classes, that can be used to use regex. for example the following code does, that you want

String toCheck = '1a2';
Map<Integer, String> descriptionToGroupNumber = new Map<Integer, String>{
    1 => 'first',
    2 => 'second',
    3 => 'third',
    4 => 'fourth',
    5 => 'fifth'
};
Pattern pat = Pattern.compile('(\\d)(\\D)(\\d)');
Matcher match = pat.matcher(toCheck);
Integer groupsToCapture = match.groupCount();
while(match.find()){
    String output = '';
    for(Integer i = 1; i <= groupsToCapture; i++){
        if(i != 1){
           output +=' '; 
        }
        output +=descriptionToGroupNumber.get(i)+': '+ match.group(i);
        if(i != groupsToCapture){
           output+=';';
        }
    }
    System.debug(output);  
}

output is

DEBUG|first: 1; second: a; third: 2

\1 equals to capturing specific group match.group(1)

3
  • Thanks for the first answer, Alex. I'm looking for a solution that isn't hard-constrained to only process three capture groups. The number of capture groups is variable: could be 2, 3, 5 or any number.
    – Marty C.
    Commented Jul 14, 2017 at 13:56
  • Thank you also for pointing out the unclear requirement in my question. I've edited the question to explain that I'm seeking a dynamic solution.
    – Marty C.
    Commented Jul 14, 2017 at 13:57
  • @MartyC. I've updated my answer with case, when there could be unknown number of groups Commented Jul 14, 2017 at 14:06
6

You can use $# to reference a capture group ($1 is the first, $2 is the second, etc.)

For your case I ran this:

System.debug('1a2'.replaceAll('(\\d)(\\D)(\\d)', 'first: $1; second: $2, third: $3'));
System.debug('8o8'.replaceAll('(\\d)(\\D)(\\d)', 'first: $1; second: $2, third: $3'));

And got this:

first: 1; second: a, third: 2
first: 8; second: o, third: 8

You must log in to answer this question.

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