Форумы портала PHP.SU » PHP » Регулярные выражения » Пример с опережающей проверкой из Фридла

Страниц (1): [1]
 

1. mstdmstd - 21 Июня, 2017 - 10:20:38 - перейти к сообщению
Всем привет,
Разбираюсь с Дж.Фридл - Регулярные выражения, 3-е изд.[2008].pdf
В примере с опережающей проверкой
пытаюсь выполнить прнимер в php:
Цитата:
Формальная постановка задачи уже приводилась выше: «вставить за
пятые во всех позициях, у которых количество цифр справа кратно
трем, а слева есть хотя бы одна цифра». .


CODE (htmlphp):
скопировать код в буфер обмена
  1.         $str= "The US population is 298444215 j», к";
  2.         $pattern = "~
  3.                 ((?<=\d))  # а слева есть хотя бы одна цифра
  4.                ((?=(\d\d\d)+$))  # , у которых количество цифр справа кратно трем
  5.            ~isUx";
  6.       $matches     = preg_replace($pattern, $str, "$1,$2");

И вывод:


1) В чем ошибка ?
2) А нет ли к этой книге примеров на пхп? Можеть кто делал? Особенно с опережающей проверкой...
Есть определенные сложности с понимаем примеров и хочется видеть рабочие примеры...

Спасибо!
2. Мелкий - 21 Июня, 2017 - 11:07:34 - перейти к сообщению
Для начала вы просто напутали порядок параметров у preg_replace.
Второй момент - позиционные проверки не имеют длины. Поэтому только их брать в круглые скобки лишено смысла.
И третье: (\d\d\d)+$. Конец строки затребован? Да. А есть в тексте место, где после 3 цифр будет конец обрабатываемой строки? Нет, такого места нет.
3. mstdmstd - 21 Июня, 2017 - 14:08:06 - перейти к сообщению
Спасибо !
с пп1-2 понятно.
с п3 не сoвсем
В результате получилось:
PHP:
скопировать код в буфер обмена
  1.         $str= "The US population is 298444215 lorem";
  2.         $pattern = "~
  3.                (?<=\d)  # а слева есть хотя бы одна цифра
  4.                (?=(\d\d\d)+)  # , у которых количество цифр справа кратно трем
  5.            ~isUx";
  6.        $matches     = preg_replace($pattern, ",", $str);
  7.  
И на выводе :
PHP:
скопировать код в буфер обмена
  1. $matches::The US population is 2,9,8,4,4,4,215 lorem

?
4. Мелкий - 21 Июня, 2017 - 14:32:24 - перейти к сообщению
С точки зрения конечного автомата регулярки всё правильно.
CODE (htmlphp):
скопировать код в буфер обмена
  1. The US population is 298444215 lorem
  2.                      ^

Вот в этой позиции есть первое совпадение: 2 есть цифра, далее как минимум 3 цифры. Значит заменяем и передвигаем позицию на символ после выполненной замены
CODE (htmlphp):
скопировать код в буфер обмена
  1. The US population is 2,98444215 lorem
  2.                        ^

9 это тоже цифра, и далее есть ещё как минимум 3 цифры, снова заменяем.
И т.д. пока утверждение о 3 цифрах после позиции не становится ложным.
5. rgl - 28 Августа, 2017 - 14:56:15 - перейти к сообщению
mstdmstd пишет:
(?=(\d\d\d)+) # , у которых количество цифр справа кратно трем

Может, так: (?=(\d\d\d)+(\D|$)) # , у которых количество цифр справа кратно трем

Т.е. количество цифр кратно трем, когда после одной или нескольких троек идет не цифра или вообще ничего нет, а у вас такой проверки нет, т.е. проверятеся что есть хотя бы одна тройка, а что дальше - не важно
PHP:
скопировать код в буфер обмена
  1. $str1 = 'The US population is 298444215 lorem';
  2. $str2 = 'The US population is 298444215';
  3.  
  4. $pattern = '/(?<=\d)(?=(?:\d\d\d)+(?:\D|$))/';
  5.  
  6. $matches1 = preg_replace($pattern, ',', $str1);
  7. $matches2 = preg_replace($pattern, ',', $str2 );
  8.  
  9. echo "$matches1\n$matches2\n";
  10.  

P.S.
Вариант без заглядывания назад:
PHP:
скопировать код в буфер обмена
  1. $str1 = 'The US population is 298444215 lorem';
  2. $str2 = 'The US population is 298444215';
  3.  
  4. $pattern = '/(\d)(?=(?:\d\d\d)+(?:\D|$))/';
  5.  
  6. $matches1 = preg_replace($pattern, '$1,', $str1);
  7. $matches2 = preg_replace($pattern, '$1,', $str2 );
  8.  
  9. echo "$matches1\n$matches2\n";
  10.  

 

Powered by ExBB FM 1.0 RC1