【发布时间】:2011-11-28 11:37:30
【问题描述】:
多行文字
某些行具有以下模式/^aaa(B+)(.*)/
- 以“aaa”开头
- 后跟数字“B”(1 到 9)
- 剩余的行
需要构造一个函数得到什么:
- 标量中的文本,以及
- shifting参数如何移动B的数量
例如:
change_ab(2,$text) # and the function will add 2 B
change_ab(-1, $text) #the function will remove one B
编辑:添加了一些示例 - (结果需要有 min 1B 或 max 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);
}
基于 Zaid 回答的新版本:
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:如果有人可以给出更好的问题标题 - 请。改变它。
【问题讨论】:
-
天啊-我的错-我忘了写下来,结果我需要至少 1B 或最多 9B。我在我的源代码中有这些检查 - 但不幸的是我忘了把它写到文本中......我得到的所有解决方案都是从“aaaB”制作的,只有“aaa”。我的错。 ;(
-
而不是
fixshift,我想说有足够的调整来证明使用辅助变量是合理的:s{...}{ my $reps = length($1) + $_[0]; 'B' x $reps < 1 ? 1 : $reps > 9 ? 9 : $reps }。现在看来,您似乎需要重新审视大局,以了解为什么首先需要进行如此复杂的操作。 -
简单地说,输入已经定义了格式——来自一个更大的系统,所以不能改变它。输出格式必须与输入相同(将替换它)。我需要改变'B'的数量。就这样。你的解决方案很棒。谢谢。 :)
标签: perl