-3

I am using the compile method for the pattern class in order to separate digits (street house number) from a string into a number field, and the non-digits (street) into a string field. \d* gives me the numbers in the text field. But how would I only get the first number in the following examples:

'20a Test Street Appt. 3';
'Test Street 20/4';
'Test Street 1-15';

When I want to caputre the string only, I can use [^\d]*. How can I remove additional characters like in the following examples:

'Test Strasse 17 c' => The 'c';
'20a Test Strasse' => The 'a';
'Test Strasse 20/2' => The '/';

The code I am using for the regex is as follows:

// First, instantiate a new Pattern object "MyPattern"
Pattern numberPattern = Pattern.compile('[\\d]'); //correct regex here
Pattern streetPattern = Pattern.compile('[\\d]'); //correct regex here
// Then instantiate a new Matcher object "MyMatcher"
if(account.BillingStreet != null){
   Matcher numberMatcher = numberPattern.matcher(account.BillingStreet);
   Matcher streetMatcher = streetPattern.matcher(account.BillingStreet);

   // You can use the system static method assert to verify the match
   if (numberMatcher.matches()) {
      account.HouseNumber__c = numberMatcher.group(1);
   }
   if (streetMatcher.matches()) {
      account.Street_Custom__c = streetMatcher.group(1);
   }
}
2

You should almost never use matches(), but instead typically prefer find(). My primary suggestion to you here is that you add some word boundaries to your patterns (\b). You can actually condense your whole search into just one pattern:

^(\b\D+\b)?\s*(\b.*?\d.*?\b)\s*(\b\D+\b)?$

The link above explains each component of the expression. There are two basic pieces of this puzzle:

  1. (\b\D+\b)?
    • \b - assert position at a word boundary
    • \D - matches any character that's not a digit
    • + - matches between one and unlimited times, as many times as possible, giving back as needed
    • (...)? - matches between zero and unlimited times, as few times as possible, expanding as needed
    • Summary: If there are any non-digit characters at the beginning of the string, match as many as you can (ending in a word boundary). Note the entire group is optional ((...)?), since you may have numbers either before or after.
  2. (\b.*\d+.*?\b)
    • .*? - there can be any number of characters before or after
    • *? - matches between zero and unlimited times, as few times as possible, expanding as needed
    • \d+ - there must be at least one digit
    • Summary: If there are any digit characters, match them and any others so long as you do not hit a word boundary.

I added in the \s* just to ignore any whitespace between the capturing groups, but it is not strictly necessary. Note that the above will probably not do what you want if you have numeric street names. To use it in code, I would do something like:

Pattern streetPattern = Pattern.compile('^(\\b\\D+\\b)?\\s*(\\b.*?\\d.*?\\b)\\s*(\\b\\D+\\b)?$');
Matcher m = streetPattern.matcher('20a Test Strasse');
if (m.find())
{
    String group1 = m.group(1);
    String group3 = m.group(3);
    if (group1 == null && group3 == null)
    {
        // you have only the numeric bit
    }
    else if (group1 != null && group3 != null)
    {
        // the numbers are in the middle
    }
    else
    {
        String streetName = (group1 != null) ? group1 : group3;
        String streetNumber = m.group(2);
        system.debug(streetName);
        system.debug(streetNumber);
    }
}

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.