3

I want to extract two substrings from a predictably formatted string.

Each string is comprised of letters followed by numbers.

Inputs & Outputs:

  • MAU120 => MAU and 120
  • MAUL345 => MAUL and 345
  • MAUW23 => MAUW and 23
3
  • 2
    Would we ever have a number without letters, or letters without numbers? Commented Oct 12, 2011 at 18:09
  • Does it always start with MAU and end with a number like your examples? It's more helpful if you can specify a general pattern rather than random examples. Commented Oct 12, 2011 at 18:15
  • Consider this answer stackoverflow.com/questions/18031055/… Commented Dec 23, 2016 at 13:53

4 Answers 4

7
$matches = array();

if ( preg_match('/^([A-Z]+)([0-9]+)$/i', 'MAUL345', $matches) ) {
    echo $matches[1]; // MAUL
    echo $matches[2]; // 345 
}

If you require the MAU you can do:

/^(MAU[A-Z]*)([0-9]+)$/i

Removing i modifier at the end will make the regex case-sensitive.

Sign up to request clarification or add additional context in comments.

3 Comments

Also matches mAuL345 and bob2.
OP never stated that MAU was a requirement, nor case. I've edited my answer to show a way to require MAU and added info about the case modifier.
Sorry @webbie. I wasn't criticizing your approach. I was merely pointing out some matches that the OP didn't specify by example. The problem is that the OP didn't say much of anything concerning the desired pattern. Nevertheless, this is a much better answer than it was. +1 :-)
3

Try this regular expression:

/(\D*)(\d*)/

PHP code:

$matches = array();

var_dump( preg_match('/(\D*)(\d*)/', 'MAUL345', $matches) );
var_dump( $matches );

3 Comments

That looks dangerous. . . "?@#!123" now parses. . .
?@#!123 will be parsed as ?@#! and 123. That probably introduced characters that will correctly parse that are not intended by the OP. Hence, looks dangerous.
The OP just says "the substring from string before first number occurs" (title) -- the examples specifically use letters, but the question itself does not exclude them...
1

Taken literally from your examples:

<?php
$tests = array('MAU120', 'MAUL345', 'MAUW23', 'bob2', '?@#!123', 'In the MAUX123 middle.');

header('Content-type: text/plain');
foreach($tests as $test)
{
    preg_match('/(MAU[A-Z]?)(\d+)/', $test, $matches);
    $str = isset($matches[1]) ? $matches[1] : '';
    $num = isset($matches[2]) ? $matches[2] : '';
    printf("\$str = %s\n\$num = %d\n\n", $str, $num);
}
?>

Produces:

$test = MAU120
$str = MAU
$num = 120

$test = MAUL345
$str = MAUL
$num = 345

$test = MAUW23
$str = MAUW
$num = 23

$test = bob2
$str = 
$num = 0

$test = ?@#!123
$str = 
$num = 0

$test = In the MAUX123 middle.
$str = MAUX
$num = 123

Comments

0

When you can guarantee that there will be one or more non-numbers and then one or more numbers, you can call upon sscanf() to parse the string.

The native function has multiple advantages over preg_match().

  1. It doesn't return the fullstring match.
  2. It will allow you to type cast substrings depending on the format placeholder you use.
  3. It can return its array or create reference variables -- depending on the number of parameters you feed it.

Code: (Demo)

$tests = [
    'MAU120',
    'MAUL345',
    'MAUW23',
];

foreach ($tests as $test) {
    sscanf($test, '%[^0-9]%d', $letters, $numbers);
    var_export([$letters, $numbers]);
    echo "\n";
}

Output: (notice that the numbers are cast as integer type)

array (
  0 => 'MAU',
  1 => 120,
)
array (
  0 => 'MAUL',
  1 => 345,
)
array (
  0 => 'MAUW',
  1 => 23,
)

If your numbers might start with zero(s) and you want to retain them, you can use %s instead of %d to capture the non-whitespaces substring. If you use %s, then the digits will be cast as a string instead of int-type.

Alternative syntax: (Demo)

foreach ($tests as $test) {
    var_export(sscanf($test, '%[^0-9]%d'));
    echo "\n";
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.