function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Paweł WoźniakPaweł Woźniak 

How to replace string with regex pattern, matcher and replaceFirst ? (Regex too complicated)

Hi. 
I want to replace some specific words in string with anothers using pattern and matcher. Example: I want format nicely SOQL query so:
[ SELECT Id, Name FROM Account WHERE Name =  'John' ]
should be changed to:
[SELECT
    Id, Name
FROM
    Account
WHERE 
    Name = 'John']

The code:
 

String convertInput = '[ SELECT Id, Name FROM Account WHERE Name =  \'John\' ]';
String convertOutput = '';
String regExp = '(SELECT|FROM|WHERE)';

Pattern p = Pattern.compile(regExp);      
Matcher m = p.matcher(convertInput);
    while (m.find() == true) {          
        convertOutput = m.replaceFirst('\n' + m.group(1) + '\n');

    } 
System.debug(convertOutput);

Gives error: System.LimitException: Regex too complicated

Where code:
String convertInput = '[ SELECT Id, Name FROM Account WHERE Name =  \'John\' ]';
String convertOutput = '';
String regExp = '(SELECT|FROM|WHERE)';

Pattern p = Pattern.compile(regExp);      
Matcher m = p.matcher(convertInput);
    while (m.find() == true) {          
        convertOutput = m.replaceAll('\n' + m.group(1) + '\n');
    } 
System.debug(convertOutput);

Gives output:
SELECT
Id, Name
SELECT
Account
SELECT
Name = 'John' ]

So I am confused what is so complicated in replaceFirst?
Do you have any suggestions how to solve that?
Best Answer chosen by Paweł Woźniak
David ZhuDavid Zhu
It seems replaceFirst cannot handle different matches in the same matcher. I came up with the following code and it exports the data you want.
 
String convertInput = '[ SELECT Id, Name FROM Account WHERE Name =  \'John\' ]';
String convertOutput = '';
String[] regExps = new string[]{'(SELECT)','(FROM)','(WHERE)'};

for(string regExp : regExps)
{
Pattern p = Pattern.compile(regExp);      
Matcher m = p.matcher(convertInput);
    while (m.find() == true) {          
        convertOutput = m.replacefirst('\n' + m.group(1) + '\n');
		convertInput = convertOutput;
    } 
}
System.debug(convertOutput);

 

All Answers

David ZhuDavid Zhu
It seems replaceFirst cannot handle different matches in the same matcher. I came up with the following code and it exports the data you want.
 
String convertInput = '[ SELECT Id, Name FROM Account WHERE Name =  \'John\' ]';
String convertOutput = '';
String[] regExps = new string[]{'(SELECT)','(FROM)','(WHERE)'};

for(string regExp : regExps)
{
Pattern p = Pattern.compile(regExp);      
Matcher m = p.matcher(convertInput);
    while (m.find() == true) {          
        convertOutput = m.replacefirst('\n' + m.group(1) + '\n');
		convertInput = convertOutput;
    } 
}
System.debug(convertOutput);

 
This was selected as the best answer
Paweł WoźniakPaweł Woźniak
This is nice workaround, works as desired. Thank you.
APM91APM91
Hi,
I wanted to add a prefix as abc__xyz__c as I insert a string xyz__c
using custom controller