I need a regex for the following pattern:
a single character from [e-g] followed by one or more numbers that ends with character 'c'.
for example e123f654g933c expected result:
Array
(
[0] => Array
(
[0] => e123
[1] => f654
[2] => g933
)
)
or
e123f654g933ce99f77g66c expected result:
Array
(
[0] => Array
(
[0] => e123
[1] => f654
[2] => g933
),
[1] => Array
(
[0] => e99
[1] => f77
[2] => g66
)
)
I tried using the following but I don't know what to do with 'c' part. I used this ([e-g]{1}[0-9]{1,}c)+ but it fails.
$subject="e123f654g933ce99f786g776c";
preg_match_all('/[e-g]{1}[0-9]{1,}/', $subject, $match);
print '<pre>' . print_r($match,1) . '</pre>';
Array
(
[0] => Array
(
[0] => e123
[1] => f654
[2] => g933
[3] => e99
[4] => f786
[5] => g776
)
)
thanks.
I couldn't manage to generate your multi dimensional output array via a single regex function call.
Code (Demo: https://3v4l.org/f5nnk )
$strings=[
'e123f654g933c',
'e123f654g933ce99f77g66c'
];
foreach($strings as $string){
var_export(
array_map(
function($v){
return preg_match_all('/[e-g]\d+/',$v,$out2)?$out2[0]:[]; // split the groups by string format
// or return preg_split('/\d+\K/',$v,NULL,PREG_SPLIT_NO_EMPTY);
// or return preg_split('/(?=[e-g])/',$v,NULL,PREG_SPLIT_NO_EMPTY);
},
preg_match_all('/(?:[e-g]\d+)+(?=c)/',$string,$out1)?$out1[0]:[] // split into groups using c
// or explode('c',rtrim($string,'c'))
// or array_slice(explode('c',$string),0,-1)
// or preg_split('/c/',$string,NULL,PREG_SPLIT_NO_EMPTY)
)
);
echo"
";
}
Output:
array (
0 =>
array (
0 => 'e123',
1 => 'f654',
2 => 'g933',
),
)
array (
0 =>
array (
0 => 'e123',
1 => 'f654',
2 => 'g933',
),
1 =>
array (
0 => 'e99',
1 => 'f77',
2 => 'g66',
),
)
It seems you are looking for
[e-g]\d+
PHP
like so...<?php
$strings = ['e123f654g933c', 'e123f654g933ce99f77g66c'];
$regex = '~[e-g]\d+~';
foreach ($strings as $string) {
if (preg_match_all($regex, $string, $matches)) {
print_r($matches[0]);
}
}
?>
Array
(
[0] => e123
[1] => f654
[2] => g933
)
Array
(
[0] => e123
[1] => f654
[2] => g933
[3] => e99
[4] => f77
[5] => g66
)
You may use
'~(?:\G(?!^)|(?=(?:[e-g]\d+)+c))[e-g]\d+~'
See the regex demo. In short, due to the (?:\G(?!^)|(?=(?:[e-g]\d+)+c))
part, [e-g]\d+
will only match when in between 1 or more occurrences of [e-g]\d+
and c
.
Details
(?:\G(?!^)|(?=(?:[e-g]\d+)+c))
- match the end of the last successful match (\G(?!^)
) or (|
) the location followed with an e
, f
or g
letter followed with 1+ digits, 1+ occurrences (due to the(?=(?:[e-g]\d+)+c)
positive lookahead)[e-g]\d+
- an e
, f
or g
letter followed with 1+ digits$re = '/(?:\G(?!^)|(?=(?:[e-g]\d+)+c))[e-g]\d+/';
$str = 'e123f654g933c and e123f654g933ce99f77g66c';
preg_match_all($re, $str, $matches);
print_r($matches[0]);
// => Array ( [0] => e123 [1] => f654 [2] => g933 [3] => e123 [4] => f654 [5] => g933 [6] => e99 [7] => f77 [8] => g66 )
You can't easily achieve this with a single RegExp. The solution is to split the string at the occurrences of 'c', handle the parts separately, and then build the result array:
<?php
$strings = [
'e123f654g933c',
'e123f654g933ce99f77g66c',
];
foreach ($strings as $input)
{
print_r(match($input));
}
function match($input)
{
$result = [];
$parts = array_filter(explode('c', $input));
foreach ($parts as $part)
{
preg_match_all('~[e-g]\d+~', $part, $matches);
$result[] = $matches[0];
}
return $result;
}
The output will be
Array
(
[0] => Array
(
[0] => e123
[1] => f654
[2] => g933
)
)
Array
(
[0] => Array
(
[0] => e123
[1] => f654
[2] => g933
)
[1] => Array
(
[0] => e99
[1] => f77
[2] => g66
)
)