Здравствуйте. Только что обнаружил неприятную вещь и хотел бы получить совет от знатоков. Суть проблемы. При использовании (.*?) В не жадном режиме. И после этих скобок мы ни указываем ни один символ, то данное правило не срабатывает. Примеры. PHP: $text = 'Привет! страт удали меня стоп а этот стоп не удалять.'; $value = preg_replace('#страт(.*?)стоп#su', '', $text); echo $value; Результат верный. Привет! а этот стоп не удалять. А теперь немного меняем правило. PHP: $text = 'Привет! страт удали меня стоп а этот стоп не удалять.'; $value = preg_replace('#страт(.*?)#su', '', $text); echo $value; Результат Привет! удали меня стоп а этот стоп не удалять. то есть видно что условие (.*?) не сработало. Как поправить что бы оно отрабатывало до конца всего текста. Если оставить по умолчанию жадный режим. то есть вот так (.*) то первое правило отработается неверно PHP: $text = 'Привет! страт удали меня стоп а этот стоп не удалять.'; $value = preg_replace('#страт(.*)стоп#su', '', $text); echo $value; Результат Привет! не удалять. Проблема в том что это правило составляется пользователем, и входной текст заранее не известен. И условия правила. Это некая функция которая помогает пользователям форматировать текст. Пользователь вводит страт{skip}стоп | Удалить И человеко понятное правило преобразовываю в регулярку которая делает удаление. Подытожу. Как в регулярный выражениях сделать что бы если после скобок (.*?) ничего не написано, они отрабатывали до конца текста. А если есть что то, то до первого совпадения.
PHP: <?php $fun = function ( string ...$string ): string { $first = strpos ( $string[0], $string[1] ) + strlen ( $string[1] ); $last = strpos ( substr ( $string[0], $first ), $string[2] ); return strtr ( $string[0], [ $string[1].substr ( $string[0], $first, $last ).$string[2] => '' ] ); }; echo $fun( 'Привет! страт удали меня стоп а этот стоп не удалять.', 'страт', 'стоп' ); --- Добавлено --- PHP: <?php $fun = function ( string ...$string ): string { return trim ( substr ( $string[0], 0, strpos ( $string[0], $string[1] ) ), ' ' ) . substr ( $string[0], strpos ( $string[0], $string[2] ) + strlen ( $string[2] ) ); }; echo $fun( 'Привет! страт удали меня стоп а этот стоп не удалять.', 'страт', 'стоп' );
проверяй наличие СТОП. если есть, возвращай одно регулярное выражение, если нет - другое. в чем проблема?
Проблема в том что на стороне клиента есть форма для вода правил в понятном для обычного человека формате. А именно. Любой текст|На что заменить. И здесь применяется спец тег {skip} который значит любой текст. Или его отсутствие. Так вот у меня есть проблемы в понимании, как реализовать учитывая то что {skip} в правой стороне может быть как один так и 1000 Сейчас все работает так. PHP: //Фунция составления герулярного выражения для левой части поиск замена public function pregRegLeft($data){ //Отлавливаем регулярные вырежения в правилах поиск замена if(preg_match('#^\{reg\[(.*)\]\}$#', $data, $reg)){ $reg = htmlspecialchars_decode($reg[1]); }else{ $reg = preg_quote(htmlspecialchars_decode($data), '#'); //Что заменяем $what = ['\{skip\}']; //Чем заменяем $than = ['(.*?)']; //Замена $reg = str_ireplace($what, $than, $reg); //Формируем полноценный патерн $reg = '#'.$reg.'#su'; } return $reg; } По сути в этой части кода выполняется найди {skip} и замени его на (.*?) При подходу с проверкой есть ли вторая или больше частей. Это довольно сложно. И пока хотел бы узнать нету ли в регуляторах какого то флага при включении которого можно было бы заставить (.*?) при отсутствии второй части совпадать со всем оставшимся текстом. --- Добавлено --- Да но никто не гарантирует что после (.*?) будет именно конец строки.
у меня такая же проблема вылезла https://php.ru/forum/threads/pochemu-ne-rabotaet-vyrazhenie.78034/ вот так совпадение