Совпадение будет найдено, но только
и строку
abc
Совпадение будет найдено, но только при третьей итерации. \w* захватит 0 символов, а литерал c совпадет с символом c. Если в "жадном" режиме квантификатор внутри атомарной группировки захватывает все и не отдает, то в минимальном режиме он берет минимум возможного и ничего больше.
Если бы мы вынесли квантификатор за пределы атомарной группировки:
(?>\w)*c (?>\w)*?c
то совпадения были бы найдены в обоих случаях, причем, с начала строки. Состояния квантификатора, стоящего за атомарной скобкой, не уничтожаются. В этих случаях атомарная группировка вообще не нужна, т.к. нет сохраненных состояний, которые она могла бы удалить.
Вот более практический и сложный пример: пусть нам надо округлять числа типа
23.34000012 23.345000023 34.4000025 456.00
так, чтобы после десятичной точки оставалось минимум два знака, а третий знак чтобы присутствовал, только если он не равен нулю. В приведенном примере должно получиться так:
23.34 23.345 34.40 456.00
Округление мы будем делать оператором s/…/…/. Поставим еще условие, что он не должен ничего менять, если число уже имеет правильный вид. Тогда получалась бы замена цифр самих на себя.
Вначале нас интересует десятичная точка: \., затем - две обязательных цифры: \d\d. За ними может идти цифра от 1 до 9, а может и не идти: [1-9]?. Все это мы возьмем в захватывающие скобки, чтобы этим заменить все от точки до конца числа. А после еще могут идти цифры: \d*, они будут удалены. Оператор получается такой:
s/(\.\d\d[1-9]?)\d*/$1/;
Но этот оператор делает замену, к примеру, в числе 23.345, меняя найденное на себя, т.е. выполняя ненужную работу. Вот пример кода:
$_='23.345'; print s/(\.\d\d[1-9]?)\d*/$1/."\n"; print $_;
Он выведет
1 23.345
Напомню, что оператор s возвращает число успешно сделанных замен. Вот, как это происходит: подшаблон
(\.\d\d[1-9]?)
совпадает с
.345
Далее цифр нет, поэтому \d* совпадает с пустой подстрокой, и т.к. совпадение найдено, то замена срабатывает. А она должна срабатывать только, если после .345 есть цифра. Давайте для этого попробуем заменить \d* на \d+ и посмотрим, что получится. А получается результат
1 23.34
Третья цифра обрезается. Это происходит потому, что теперь \d+ совпасть не с чем. Но ведь у регулярного выражения в запасе есть сохраненное состояние в подшаблоне [1-9]?. Происходит возврат внутрь скобок к этому подшаблону, и для него пробуется состояние, когда квантификатор равен нулю. В этом случае скобки совпадают с .34, а \d+ совпадает с третьей цифрой 5, поэтому пятерка из результата удаляется. Нам нужно, чтобы при совпадении подшаблона [1-9]? с третьей цифрой это совпадение не отменялось. Но для этого надо удалить данное сохраненное состояние, т.е. заключить подшаблон [1-9]? в атомарные скобки:
s/(\.\d\d(?>[1-9]?))\d+/$1/;
Теперь пример работает правильно.
Содержание Назад Вперед
Forekc.ru
Рефераты, дипломы, курсовые, выпускные и квалификационные работы, диссертации, учебники, учебные пособия, лекции, методические пособия и рекомендации, программы и курсы обучения, публикации из профильных изданий