3

In order to split my string at the point which is preceded by digit and is followed by letters as:

 $str = '12jan';

I have used

$arr = preg_split('/(?<=[0-9])(?=[a-z]+)/i',$str);  

It works file and gives the desired output. I want to update it so that it gives the same output for strings like.

$str='12 jan';
$str='12    jan';
$str='12/jan';
$str='12//jan';
$str='12/jan';
$str='12*/jan';
$str='12*//jan';

The code should work for any strings given above so that at the end of the day I have a array like

Array
(
    [0] => 12
    [1] => jan
)

Any help will be appreciated.

Caconde
  • 4,177
  • 7
  • 35
  • 32

3 Answers3

1

This may be optimized if you answer my question in the comment.

Pattern: ~(?<=[0-9])[*/ ]*(?=[a-z]+)~i

Demo

The above will match zero or more *, / and/or space characters.


On your input strings, this will be just as accurate and faster:

Pattern: ~\d+\K[^a-z]*~i
or: ~\d+\K[*/ ]*~ (no case-sensitive pattern modifier is necessary)

Demo

The above will match zero or more non-alphabetical characters immediately following the leading digit(s).


And of course preg_split's cousins can also do nicely:

Here is a battery of PHP Demos.

$strings=['12jan','12 jan','12    jan','12/jan','12//jan','12/jan','12*/jan','12*//jan'];

foreach($strings as $string){
    var_export(preg_split('~(?<=[0-9])[*/ ]*(?=[a-z]+)~i',$string));
    echo "\n";
    var_export(preg_split('~\d+\K[*/ ]*~',$string));
    echo "\n";
    var_export(preg_match('~(\d+)[/* ]*([a-z]+)~i',$string,$out)?array_slice($out,1):'fail');
    echo "\n";
    var_export(preg_match('~(\d+)[/* ]*(.+)~',$string,$out)?array_slice($out,1):'fail');
    echo "\n";
    var_export(preg_match_all('~\d+|[a-z]+~i',$string,$out)?$out[0]:'fail');
    echo "\n---\n";
}

All methods provide the same output.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • I always endeavor (and advise others) to avoid/minimize the use of capture groups, lookarounds, alternatives, and lazy quantifiers in an effort to improve performance. – mickmackusa Feb 27 '18 at 14:05
0

I have updated your code with preg_match Its gives output what exactly your needs

$str='12/jan';
preg_match('/^(\d*)[\*\s\/]*([a-z]{3})$/i', $str, $match);
print_r($match);

but the output is changed a little bit, It will be like below

array(
  0 => '12/jan', 
  1 => '12', 
  2 => 'jan'
)
Mukesh
  • 150
  • 1
  • 10
0

A simple preg_match regexp does it:

foreach (['12 jan', '12    jan', '12/jan', '12//jan', '12/jan',
          '12*/jan', '12*//jan'] as $test)
{
        unset ($matches);
        if (preg_match("#^([0-9]+)[ /*]*(.*)#", $test, $matches)) {
                var_export( [$matches[1], $matches[2]] );
        }
        else {
                print "Failed for '$test'.\n";
        }
}

The regexp is:

  • start with numbers -> group #1
  • have 0 or more of space, slash or stars
  • take all the rest -> group #2
t3o
  • 329
  • 1
  • 10