Как объединить функции поиска в строке символов для дальнейшей логики?
$inputString = '->11гe+20∆∆A+4µcњil->5•Ћ®†Ѓ p+5f-7Ќ¬f pro+10g+1悦ra->58->44m+1*m+2a喜er!';
$keywords = preg_quote($inputString, '/');
//поиск чисел по первому символу >
preg_match_all('/>(\d+)/',$keywords,$output);
$toDelete = 1;
$result2 = count($output[0]);
for ($i=0;$i<$result2;$i++){
$result1[$i] = substr( $output[0][$i], $toDelete);
}
//print($result1[0]);
//убираем уже примененные символы и меняем символ плюс на другой для исключения ошибки и повторений выборки
$inputString2 = str_replace('->','',$inputString);
$inputString3 = str_replace('+','<',$inputString2);
//поиск чисел по второму символу -
preg_match_all('/-(\d+)/',$inputString3,$output2);
$toDelete = 1;
$result22 = count($output2[0]);
for ($i=0;$i<$result22;$i++){
$result12[$i] = substr( $output2[0][$i], $toDelete);
}
//print($result12[0]);
//поиск чисел по третьему символу <
preg_match_all('/<(\d+)/',$inputString3,$output3);
$toDelete = 1;
$result23 = count($output3[0]);
for ($i=0;$i<$result23;$i++){
$result13[$i] = substr( $output3[0][$i], $toDelete);
}
//print($result13[0]);
//
$res = mb_substr($inputString,$result1[0],1);
//$res2 = substr($inputString,11,10);
//print($res);
//print($res2);
$count1 = count($result1);
for ($j=0;$j<$count1;$j++){
$res[$j] = mb_substr($inputString,$result1[$j],1);
}
print ($res);
как же мне объединить эти функции во одну?
мне нужно в указанной строке
$inputString = '->11гe+20∆∆A+4µcњil->5•Ћ®†Ѓ p+5f-7Ќ¬f pro+10g+1悦ra->58->44m+1*m+2a喜er!';
Начинать чтение нужно с крайнего левого символа и двигаться вправо.
- Если вы сталкиваетесь с любым символом, кроме специальных обозначений, то данный символ без изменений попадает в результирующую строчку.
- Специальными обозначениями являются "->", "+", "-". После специального обозначения всегда идет число, являющееся аргументом.
- "->" — вам необходимо перейти к символу с номером, записанном в аргументе (счет начинается с 0).
- "+" — пропустить столько символов, сколько записано в аргументе. Отсчет начинается после аргумента.
- "-" — аналогично, но перемещение происходит назад (влево)
Ответы (1 шт):
Я тут было написал в комментариях, что регулярные выражения не особо подходят для этой задачи, однако, если вспомнить про наличие параметра PREG_OFFSET_CAPTURE, то они весьма помогают в решении задачи. Так что чтобы исправить свой косяк, ниже пример решения данной задачи.
Очевидно, с использованием регулярок нам легко найти все управляющие конструкции в данной строке. Регулярка простая: (->|\+|-)(\d+)/ имеет две группы захвата, первая выбираем команду, вторая аргумент.
Упомянутый выше PREG_OFFSET_CAPTURE позволяет сохранить позицию в строке, на которой было соответствие. Небольшая проблема в том, что это смещение в байтах, а не символах.
Находим соотвествия:
preg_match_all('/(->|\+|-)(\d+)/u', $inputString, $matches, PREG_OFFSET_CAPTURE);
в результате у нас в $matches будут традиционно 3 массива (полный, первая группа, вторая группа). Но сами значения массива это не просто соотвествия, а массив из двух элементов - соответствие и позиция (смещение).
Преобразуем все эти соответствия в удобный нам вид:
$ops = array_map(function($all, $c, $v) use ($inputString){
return [
'cmd' => $c[0],
'arg' => $v[0],
'pos' => mb_strlen(substr($inputString,0, $c[1])),
'cmdlen' => mb_strlen($all[0]),
];
}, ...$matches);
$ops = array_column($ops, null, 'pos');
на выходе получим массив операций (фрагмент):
[6] => Array ( // индекс - позиция
[cmd] => + // команда
[arg] => 20 // аргумент
[pos] => 6 // позиция
[cmdlen] => 3 // длина команды с аргументом
)
Далее все просто. начиная с нуля, делаем цикл, пока не достигнем конца строки (длины). Смотрим, есть ли текущаия позиция в массиве команд (индекс). Если нашлось, то обрабатываем команду, сдвигаем позицию, так как надо. Если нет, то добавляем символ к результату.
$idx = 0;
$len = mb_strlen($inputString);
$result = "";
while($idx <= $len){
$op = $ops[$idx] ?? null;
if($op){
switch($op['cmd']){
case '->': $idx = $op['arg']; break;
case '-': $idx -= $op['arg']; break;
case '+': $idx += $op['arg'] + $op['cmdlen']; break;
}
continue;
}
$result .= mb_substr($inputString, $idx++, 1);
}
echo $result;