0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

String.split(regExp, limit)を使用したときに発生する"Regex too complex"

Last updated at Posted at 2023-03-13

前置き

CSVデータを改行コードやカンマで分割してListに収めようとすると、
データサイズが大きすぎる場合に以下エラーが発生しました。

System.Exception:Regex too complex

Error 'Regex too complicated' in Apex - Salesforce Help

上記サイトにも記載があるように、
正規表現が入力シーケンスにアクセスできる回数には制限があるらしいです。

対処方法

以下に対処方法が記載してありました。

Pattern オブジェクトと Matcher オブジェクトを使用している場合は、Matcher をリセットすることで、この制限を定期的にリセットできます。
とのこと

ApexClass
/**
* Split a string of any size, while avoiding the dreaded 'Regex too complicated'
* error, which the String.split(String) method causes on some large inputs.
*
* Note that this method does not avoid other errors, such as those related to 
* excess heap size or CPU time.
*/
List<String> safeSplit(String inStr, String delim)
{
    Integer regexFindLimit = 100;
    Integer regexFindCount = 0;
    
    List<String> output = new List<String>();
    
    Matcher m = Pattern.compile(delim).matcher(inStr);
    
    Integer lastEnd = 0;

    while(!m.hitEnd())
    {
        while(regexFindCount < regexFindLimit && !m.hitEnd())
        {
            if(m.find())
            {
                output.add(inStr.substring(lastEnd, m.start()));  
                lastEnd = m.end();
            }
            else
            {
                output.add(inStr.substring(lastEnd));
                lastEnd = inStr.length();
            }
            
            regexFindCount++;
        }

        // Note: Using region() to advance instead of substring() saves 
        // drastically on heap size. Nonetheless, we still must reset the 
        // (unmodified) input sequence to avoid a 'Regex too complicated' 
        // error.
        m.reset(inStr);        
        m.region(lastEnd, m.regionEnd());
        
        regexFindCount = 0;
    }
    
    return output;
}

// Testing code
///////////////////

Integer numRepeats = 50000;
String bigInput = 'All work and no play makes Jack a dull boy.\r\n'.repeat(numRepeats);

// This generates a 'Regex too complicated' exception.
//
// List<String> a = bigInput.split('\r\n');

// This avoids a 'Regex too complicated' exception.
//
String[] a = safeSplit(bigInput, '\r\n');

System.assertEquals(numRepeats+1, a.size());
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?