Let's say we have the following data, with the code to match the pattern we'd like, in this case we're catching all numbers and unicode fractions.
$array = array('1 ½ cups','¼ cup','2 tablespoons', '½ cup', '1/3 cup', '2 large', '1 ½ teaspoons', '2 tablespoons', 'Large egg', '1 teaspoon', '¼ teaspoon');
foreach($array as $arr){
preg_match_all("/^(?:[\p{Pd}.\/\s-]*[\d↉½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑⅒⅟])+/um", $arr, $output);
foreach($output[0] as $data){
$try[] = $data;
}
}
If we print_r($try)
we get:
Array
(
[0] => 1 ½
[1] => ¼
[2] => 2
[3] => ½
[4] => 1/3
[5] => 2
[6] => 1 ½
[7] => 2
[8] => 1
[9] => ¼
)
There are 11 items in the array, one of them being complete text, Large egg in this example.
What I'm trying to do is make preg_match_all
return an empty value for that iteration, so we'd get this instead:
Array
(
[0] => 1 ½
[1] => ¼
[2] => 2
[3] => ½
[4] => 1/3
[5] => 2
[6] => 1 ½
[7] => 2
[8] =>
[9] => 1
[10] => ¼
)
What I've tried?
I looked over the preg_match_all manual but I wasn't able to find anything that could lead me to my answer, at this point I'm thinking it might have to be done over at the regex pattern, but I'm not sure at all at this point.
It looks like each iteration can only return a maximum of one match, so preg_match_all
with the inner foreach should not be needed. You can use preg_match
and append a default blank value if there isn't a match.
foreach($array as $arr){
preg_match("/^(?:[\p{Pd}.\/\s-]*[\d↉½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑⅒⅟])+/um", $arr, $output);
$try[] = $output[0] ?? '';
}
Modify the pattern to this:
/^(?:[\p{Pd}.\/\s-]*[\d↉½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑⅒⅟]|)+/um
Notice the "OR nothing" at the end.
<?php
$array = array('1 ½ cups','¼ cup','2 tablespoons', '½ cup', '1/3 cup', '2 large', '1 ½ teaspoons', '2 tablespoons', 'Large egg', '1 teaspoon', '¼ teaspoon');
foreach($array as $arr){
preg_match_all("/^(?:[\p{Pd}.\/\s-]*[\d↉½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑⅒⅟]|)+/um", $arr, $output);
foreach($output[0] as $data){
$try[] = $data;
}
}
var_dump($try);
Result:
array(11) {
[0]=>
string(4) "1 ½"
[1]=>
string(2) "¼"
[2]=>
string(1) "2"
[3]=>
string(2) "½"
[4]=>
string(3) "1/3"
[5]=>
string(1) "2"
[6]=>
string(4) "1 ½"
[7]=>
string(1) "2"
[8]=>
string(0) ""
[9]=>
string(1) "1"
[10]=>
string(2) "¼"
}
Disclaimer: this looks like a dirty hack that is probably brittle, but it can get you in the right direction