Правильный код ниже:
letter 'c' followed by digit
letter 'c' followed by digit dash digit
digit may be followed by an other digit enclosed in square parentheses []
и создает массив, как ожидалось:
Array ( [0] => Array ( [start] => 4 [end]=> 8 ) [1] => Array ( [start] => 2 [end]=> ) [2] => Array ( [start] => 3 [end] => 5 ) [3] => Array ( [start] => 6[2] [end] => ) [4] => Array ( [start] => 8[4] [end] => 10 ) [5] => Array ( [start] => 14 [end] => 21[5] ) )
КОД:
$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; $re = "~c(?<start>\d+(?:\[\d+])?)(?:-(?<end>(?&start)?))?~"; $myarray = explode("|",$str); foreach ($myarray as $my) { preg_match_all($re, $my, $matches); $res = array_map(function($ms, $me) { return array("start" => $ms, "end" => $me); }, $matches["start"], $matches["end"]); } echo "<pre>"; print_r($res); echo "</pre>";
Теперь я хотел бы добавить другой key
со значением цифры после a
. Так, например, учитывая приведенную выше $str
$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]".
значения a
: 2
и 6
а ожидаемый массив результатов будет следующим. Обратите внимание, что 6
повторяется для каждого c
.
Array ( [0] => Array ( [a] => 2 [start] => 4 [end]=> 8 ) [1] => Array ( [a] => 6 [start] => 2 [end]=> ) [2] => Array ( [a] => 6 [start] => 3 [end] => 5 ) [3] => Array ( [a] => 6 [start] => 6[2] [end] => ) [4] => Array ( [a] => 6 [start] => 8[4] [end] => 10 ) [5] => Array ( [a] => 6 [start] => 14 [end] => 21[5] ) )
Вы можете сделать это:
$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; $re = '~(?:a(?<a>\d+))?c(?<start>\d+(?:\[\d+])?)(?:-(?<end>\g<start>))?~'; if (preg_match_all($re, $str, $matches, PREG_SET_ORDER) ) { $a = ''; // current value for "a" -----, $result = array_map(function ($i) use (&$a) { if (!empty($i['a'])) $a = $i['a']; else $i['a'] = $a; if (!isset($i['end'])) $i['end'] = ''; foreach ($i as $k=>$v) { if (is_numeric($k)) unset($i[$k]); } return $i; }, $matches); } print_r($result);
Но если вы уже точно знаете, как выглядит строковый формат, и если вам не нужно его проверять, возможно, есть более умные (и более быстрые) способы получить тот же результат.
Например, используя explode
и форматированные строки с помощью sscanf
:
$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; $parts = explode('|', $str); $result = []; $keys = ['a', 'start', 'end']; foreach($parts as $part) { foreach(explode(',', $part) as $k=>$v) { if ($k) list($start, $end) = sscanf($v, 'c%[^-]-%[^,]'); else list($a, $start, $end) = sscanf($v, 'a%dc%[^-]-%[^,]'); $result[] = array_combine($keys, [$a, $start, $end]); } } print_r($result);