Различение и замена десятичных знаков в Perl - PullRequest
0 голосов
/ 02 декабря 2018

Я хочу заменить десятичные дроби с запятыми на полные остановки в файле, и я хотел попробовать сделать это в Perl.Пример моего набора данных выглядит примерно так:

Species_1:0,12, Species_2:0,23, Species_3:2,53

Я хочу подставить десятичные дроби, но не все запятые, чтобы:

Species_1:0.12, Species_2:0.23, Species_3:2.53

Я думал, что это может работать с использованием подстановкифункция такая:

$comma_file= "Species_1:0,12 , Species_2:0,23, Species_3:2,53"

    $comma = "(:\d+/,\d)";
#match a colon, any digits after the colon, the wanted comma and digits preceding it
       if ($comma_file =~ m/$comma/g) {
           $comma_file =~ tr/,/./;
        }
print "$comma_file\n"; 

Однако, когда я попробовал это, произошло то, что все мои запятые превратились в полные стопы, а не только те, на которые я нацеливался.Это проблема с регулярным выражением или я просто неправильно выполняю подстановку совпадений?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Из показанных данных видно, что заменяемая запятая всегда должна иметь номер с каждой стороны, и что каждый такой случай должен быть заменен.Существует прекрасный ответ от GMB .

Еще один способ решения этой проблемы - использовать lookarounds

$comma_file =~ s/(?<=[0-9]),(?=[0-9])/./g;

, который должен бытьболее эффективным, так как нет копирования в $1 и $2 и квантификаторов.

Мой тест

use warnings;
use strict;
use feature 'say';

use Benchmark qw(cmpthese);

my $str = q(Species_1:0,12, Species_2:0,23, Species_3:2,53);

sub subs {
    my ($str) = @_; 
    $str =~ s/(\d+),(\d+)/$1.$2/g;
    return $str;
}

sub look {
    my ($str) = @_; 
    $str =~ s/(?<=\d),(?=\d)/./g;
    return $str;
}

die "Output not equal" if subs($str) ne look($str);

cmpthese(-3, {
    subs => sub { my $res = subs($str) },
    look => sub { my $res = look($str) },
});

с выводом

         Rate subs look
subs 256126/s   -- -46%
look 472677/s  85%   --

Этотолько одна конкретная строка, но преимущество в эффективности должно увеличиваться только с длиной строки, в то время как более длинные шаблоны (числа здесь) должны немного уменьшить это.

0 голосов
/ 03 декабря 2018

This:

use strict;
use warnings;
my $comma_file = "Species_1:0,12, Species_2:0,23, Species_3:2,53";
$comma_file =~ s/(\d+),(\d+)/$1.$2/g;
print $comma_file, "\n";

Выход:

Species_1:0.12, Species_2:0.23, Species_3:2.53

Регулярное выражение ищет запятые, содержащие по крайней мере одну цифру с обеих сторон, и заменяет их точкой.

Ваш код не работает, потому что вы сначала проверяете запятые, заключенные в цифры, и, если все в порядке, вы заменяете ВСЕ запятые точками

...