Имеет много строк текста
некоторые строки имеют следующий шаблон /^aaa(B+)(.*)/
- , начинающийся с "aaa"
- , за которым следует число "B""(От 1 до 9)
- остаток строки
необходимо построить функцию, которая получит:
- текст в скаляре и
- параметр сдвига, как смещать число Bs
, например:
change_ab(2,$text) # and the function will add 2 B
change_ab(-1, $text) #the function will remove one B
РЕДАКТИРОВАТЬ: добавлено несколько примеров - (в результате необходимочтобы иметь минимум 1B или максимум 9Bs) - в моем исходном коде есть эти условия, но я забыл написать это здесь (sry))
shifting from result
2 aaaB aaaBBB
3 aaaBB aaaBBBBB
-2 aaaBBBB aaaBB
-3 aaaBB aaaB #min.1
9 aaaBBBB aaaBBBBBBBBB #max.9
мое решение состоит в разбиении скалярного текста на строки.Не очень элегантно: (
Существует какое-то лучшее / более быстрое решение - например, одно большое регулярное выражение без необходимости расщепления?
Вот мой код:
use 5.014;
use warnings;
my $mytext = "some text
aaaB some another text
text3 here
aaaBB some text4
another textxxx
aaaBBBBXX some text4
another textzzzz
";
say change_ab(-1,$mytext);
sub change_ab {
my($bshift, $text) = @_;
my $out = "";
foreach my $line ( split(/[\r\n]/, $text) ) {
if( $line =~ /^aaa(B+)(.*)/) {
my $bcnt = length($1);
my $wantedBcnt = $bcnt + $bshift;
$wantedBcnt = 1 if $wantedBcnt < 1;
$wantedBcnt = 9 if $wantedBcnt > 9;
my $wantedBstr = sprintf("aaa%s", "B" x $wantedBcnt);
$line =~ s/^aaaB+/$wantedBstr/;
}
$out .= $line . "\n";
}
return($out);
}
новая версия, основанная наОтвет Зайда:
use 5.014;
use warnings;
my $mytext = "some text
aaaB some another text
text3 here
aaaBB some text4
another textxxx
aaaBBBBXX some text4
another textzzzz
";
say change_ab(8, $mytext);
sub change_ab {
$_[1] =~ s{(?<=^aaa)(B+)}{ 'B' x fixshift(length($1)+$_[0]) }gem;
return $_[1];
}
sub fixshift {
return 9 if $_[0] > 9;
return 1 if $_[0] < 1;
return $_[0];
}
Ps: если кто-то может дать лучшее название вопроса - пожалуйста, измените его.