Matt Stein
Matt Stein

Reputation: 3053

Split string on last occurring underscore

I've got strings which consist of a label, underscores, and an ID:

What I'd like to have are two distinct chunks:

I know that I can isolate the numeric value, then turn around and subtract that from the original string, but I'm not sure if there's a cleaner way to do this in one step. Explode's limit argument seems close, and I have a feeling there's a regex pattern that could split by only the last underscore.

Upvotes: 1

Views: 291

Answers (4)

mickmackusa
mickmackusa

Reputation: 47854

To split only on the last occurring underscore, use a pattern with a greedy match on "any" characters from the start of the string, then reset the fullstring match just before encountering the last occurring underscore. This will effectively consume the last underscore only and split the string into two parts at most. You get exactly what you intend to use, two-element arrays. preg_match() will return three-element arrays, of which the first element is of no use to you.

Code: (Demo)

$strings = ["category_4", "office_362", "core_market_56"];
foreach($strings as $string) {
  var_export(preg_split('/.*\K_/', $string));
}

Output:

array (
  0 => 'category',
  1 => '4',
)array (
  0 => 'office',
  1 => '362',
)array (
  0 => 'core_market',
  1 => '56',
)

Upvotes: 1

kba
kba

Reputation: 19466

$strings = array("category_4","office_362","core_market_56");
foreach($strings as &$string)
{
  preg_match('/(\w*)_(\d*)/', $string, $matches);
  $string = array($matches[1],$matches[2]);
}
print_r($strings);

The above will return

([0] => Array (
            [0] => category
            [1] => 4)
 [1] => Array (
            [0] => office
            [1] => 362)
 [2] => Array (
            [0] => core_market
            [1] => 56))

Upvotes: 2

bobbymcr
bobbymcr

Reputation: 24167

I figure the most efficient way for parsing purposes is to have a fixed length numeric field at the end so that you can always count an exact number of characters from the end of the string and know that the rest (minus the separator) will be the text portition.

# Example with fixed length numeric portion of 8 digits
$N = 8;
$s = "SomeText_00000001";
$text = substr($s, 0, strlen($s) - $N - 1);
$num = substr($s, -$N);

Upvotes: 1

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230286

This is the regex you want

(\w*)_(\d*)

First matched group is your word, second - number. This is based, of course, on the assumption that number is always in the end and is separated from the word by underscore.

Upvotes: 2

Related Questions