I have a string which is combination of letters and digits. For my application i have to separate a string with letters and digits: ex:If my string is "12jan" i hav to get "12" "jan" separately..
7 Answers
$numbers = preg_replace('/[^0-9]/', '', $str);
$letters = preg_replace('/[^a-zA-Z]/', '', $str);

- 1,808
- 15
- 17
-
[You don't need to invoke the regex engine twice](http://stackoverflow.com/questions/4311156/how-to-separate-letters-and-digits-from-a-string-in-php/4311202#4311202). – alex Nov 30 '10 at 07:08
-
2@alex, if it's a matter of speed, what I posted is faster in my test (100000 iterations). I believe it's clearer too. – Mike C Nov 30 '10 at 07:23
-
It is faster, by about 3 times time in my tests. I'm not which one is clearer though. – alex Nov 30 '10 at 11:44
-
There are [simpler ways to express digits and non-digits in a regex pattern](https://stackoverflow.com/a/65704778/2943403). – mickmackusa Jul 23 '21 at 00:01
You can make use of preg_split
to split your string at the point which is preceded by digit and is followed by letters as:
$arr = preg_split('/(?<=[0-9])(?=[a-z]+)/i',$str);
<?php
$str = '12jan';
$arr = preg_split('/(?<=[0-9])(?=[a-z]+)/i',$str);
print_r($arr);
Result:
Array
(
[0] => 12
[1] => jan
)
-
your code is not working if there is whitespace. `$str = 12 Jan` like that – Prashant Tapase Jun 22 '15 at 06:39
-
5If there's a whitespace, wouldn't it be easier to use explode using the space itself as a delimiter? – Adrian Pauly Aug 10 '16 at 16:28
-
@PrashantTapase just add space in the character set `[a-z]` : `[\sa-z]` – sglessard Mar 02 '18 at 17:51
-
3This code works only if digits are first. If You will change $str to 'jan12' it will output [0] => 'jan12' – Eryk Wróbel May 16 '18 at 06:41
$string = "12312313sdfsdf24234";
preg_match_all('/([0-9]+|[a-zA-Z]+)/',$string,$matches);
print_r($matches);
this might work alot better

- 10,410
- 6
- 29
- 50
-
1
-
Why bother with the capture grouping? I'd probably use a case insensitively flag. This answer is missing its educational explanation. – mickmackusa Jul 22 '21 at 23:55
preg_match_all('/^(\d+)(\w+)$/', $str, $matches);
var_dump($matches);
$day = $matches[1][0];
$month = $matches[2][0];
Of course, this only works when your strings are exactly as described "abc123" (with no whitespace appended or prepended).
If you want to get all numbers and characters, you can do it with one regex.
preg_match_all('/(\d)|(\w)/', $str, $matches);
$numbers = implode($matches[1]);
$letters = implode($matches[2]);
var_dump($numbers, $letters);

- 479,566
- 201
- 878
- 984
-
1
-
`preg_match_all('/(\d)|(.)|(\w)/', $str, $matches);` will also respect strings like '12-jan' or 'jan-12', if you want to reuse the extracted characters too. – MrMacvos Feb 20 '20 at 13:34
-
1The commented code by MrMacvos is misleading/bad, but I cannot dv it. **Do not use it.** https://3v4l.org/9tDfr and https://3v4l.org/INJ1H – mickmackusa Jul 22 '21 at 23:52
You can split the string by matching sequences of digits or non-digits, then "forgetting" the matched characters with \K
.
preg_split(
'~(?:\d+|\D+)\K~',
$string,
0,
PREG_SPLIT_NO_EMPTY
)
Or you could use matched digits as the delimiter and retain the delimiters in the output.
preg_split(
'~(\d+)~',
$string,
0,
PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
)
A demonstration of both techniques.
If you know the order of your numeric and alphabetic substrings, then sscanf()
is a perfect tool.
Code: (Demo)
var_export(sscanf('12jan', '%d%s'));
Output:
array (
0 => 12,
1 => 'jan',
)
Notice how 12
is conveniently cast as an integer as well.
sscanf()
also allows individual variables to be assigned if desired ($day
and $month
) as the 3rd and 4th parameters.

- 43,625
- 12
- 83
- 136
-
This will produce many groups when the numbers and letters are interwoven. – Dharman Jul 23 '21 at 17:41
-
Of course it will. What's the alternative? The [mcve] is so narrowly scoped that I have no way to guess how the desired output should differ if the input is extended. – mickmackusa Jul 23 '21 at 22:00
This works for me as per my requirement, you can edit as per yours
function stringSeperator($string,$type_return){
$numbers =array();
$alpha = array();
$array = str_split($string);
for($x = 0; $x< count($array); $x++){
if(is_numeric($array[$x]))
array_push($numbers,$array[$x]);
else
array_push($alpha,$array[$x]);
}// end for
$alpha = implode($alpha);
$numbers = implode($numbers);
if($type_return == 'number')
return $numbers;
elseif($type_return == 'alpha')
return $alpha;
}// end function

- 41
- 2
-
This answer is missing its educational explanation. Why not just use iterated string concatenating techniques if you are going to return strings? Using temporary arrays and imploding seems unnecessarily wasteful. – mickmackusa Jul 23 '21 at 00:03
Try This :
$string="12jan";
$chars = '';
$nums = '';
for ($index=0;$index<strlen($string);$index++) {
if(isNumber($string[$index]))
$nums .= $string[$index];
else
$chars .= $string[$index];
}
echo "Chars: -$chars-<br>Nums: -$nums-";
function isNumber($c) {
return preg_match('/[0-9]/', $c);
}
-
-
Calling `preg_match()` inside of a custom function for EVERY character in a string -- that's WAY too much overhead for this task. I would not recommend that any researchers use this option. As a result, I have dv'ed and voted to delete this answer. – mickmackusa Jul 22 '21 at 23:25