2013-08-18 6 views
1

В следующем примере я пытаюсь сохранить десятичную часть и первые 2 дробные части, а третий, если она больше, чем 0.
Так +12,37500000000392 следует заменить на 12.375Не удается заменить с помощью групп захвата?

#!/usr/bin/perl 

use strict; 
use warnings; 

my $price = 12.37500000000392; 
print "price = $price \n"; 
$price =~ s/([0-9]+)(\.[1-9]{2}[1-9]?)\d*?/$1$2/; 

print "1 = $1 \n"; 
print "2 = $2 \n"; 
print "price = $price \n"; 

Но это не Работа.
Это показывает, что $1 является 12 и $2 является .375 но цена в конце концов, до сих пор печатаются 12.37500000000392 в последнем print заявления

+0

Это проблема X/Y? Почему бы вам просто не сказать '$ price = sprintf"% g ", $ price'? – mob

ответ

4

Проблема заключается в ungreedy повторения в конце. Просто используйте

$price =~ s/([0-9]+)(\.[1-9]{2}[1-9]?)\d*/$1$2/; 

Поскольку ? делает * матч как несколько повторений, насколько это возможно - и нет никаких дополнительных условий в конце картины, которые могли бы сделать это не в состоянии - 0 повторений \d это наименьшее количество возможно, так остальные цифры просто не совпадают и, следовательно, не заменяются.

Обратите внимание, что ваш шаблон не совпадает вообще, если одна из первых двух цифр равна нулю. Вы, вероятно, хотели использовать

$price =~ s/([0-9]+)(\.[0-9]{2}[1-9]?)\d*/$1$2/; 

Кроме того, если вам не нужны целые и дробные части позже, вы могли бы немного упростить все вещи, как это:

$price =~ s/([0-9]+\.[0-9]{2}[1-9]?)\d*/$1/; 
1

Вы можете сделать это с :

$price =~ s/\.\d{2}[1-9]?\K\d*//; 
+0

обратите внимание, что '\ d' соответствует более чем' [0-9] ', и я бы соответствовал хотя бы одной цифре перед' \ .' (поскольку текущий шаблон использует '+'), но я даже не думаю, что это преимущество в производительности, чтобы оставить это. но +1 для '\ K' –