4

Does anyone know why this will not find the match.

I'm running this code

    public string cleanEmail(String body){
    String result;
    String RegExp = '(?m).*^From:.*\\n^Sent:.*\\n^To:.*\\n^Subject:.*'; 
    Matcher m = Pattern.compile(RegExp).matcher(body);
    if (m.matches()) {
        Integer position = m.start();
        result = body.substring(0, position);
    }else{
        result = 'No match';
    }
    return result;
}

The string "body" equals the following and should find a match.

email Test 6

From: xxxxx@xxxxxx.com
Sent: Wednesday, December 11, 2013 7:07 AM
To: 'xxxxx@xxxxxx.com'
Subject: FW: Case email testing

Junk

3

Assuming that I'm formatting the string correctly (escaping the single quotes, putting in new lines etc.) then for some reason the pattern you have doesn't match, but putting in a new line before the From label does work:

String RegExp = '(?m).*\\n^From:.*\\n^Sent:.*\\n^To:.*\\n^Subject:.*'; 

I'd love to be able to say why but right now I'm not to sure, I have hit some weirdness with matchers before now and don't see why the .* shouldn't pick up the newline character.

  • Thanks. I tried that and it still didn't work. Maybe I'll try doing the same with string methods, since matchers sounds unreliable. – Matt Sneller Dec 12 '13 at 17:24
2

I abandoned the matcher. Here is my solution. Hope this helps others that run into this.

    public string cleanEmail(String body){
    String result;
    String RegExp = '(?m).*^From:.*\\n^Sent:.*\\n^To:.*\\n^Subject:.*'; 
    List<String> clean = body.split(RegExp);

    if (clean.size() > 0) {
        result = clean.get(0);
    }else{
        result = 'No match';
    }
    return result;
}
1

You're observing this behavior because the '.' character class in Java (and thus Apex) Patterns doesn't match line terminators by default. You can add the DOTALL flag 's' to change this behavior (note the '(?ms)'):

String RegExp = '(?ms).*^From:.*\\n^Sent:.*\\n^To:.*\\n^Subject:.*';
// this will now match your example body:
System.assert(RegExp.matcher(body).matches());

Alternatively, you could have changed your first and last '.*' to the following:

'(?:\\n|.)'

However, be warned -- there are several flavors of line terminators, though \n is the most common. To be thorough you'd use something like the following instead of simply \n, that additionally accounts for the Windows \r\n and Unicode line terminators:

'(?:\\r\\n|[\\n\\r\\u2028\\u2029])'

As a final note, the Patterns you're using are very inefficient because of all those non-possessive greedy quantifiers. That's going to cause tons of backtracking, and thus you may notice performance degradation with larger strings.

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.