有没有更好的方法在 Perl 中添加/删除字符串中的“B”?
有很多行文本,
有些行具有以下模式 /^aaa(B+)(.*)/
- 以“aaa”开头,
- 后跟多个“B”(1 到 9),
- 其余部分该行
需要构造一个函数,得到什么:
- 标量中的文本,以及
- 移位参数如何移位 B 的数量,
例如:
change_ab(2,$text) # and the function will add 2 B
change_ab(-1, $text) #the function will remove one B
编辑:添加了一些示例 - (结果中需要有最小 1B 或最大 9B ) - 在我的源代码是这些条件,但我忘了在这里写(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:如果有人可以给出更好的问题标题 - 请更改它。
Have many lines of text
some lines has the following pattern /^aaa(B+)(.*)/
- start with "aaa"
- followed by a number of "B" (1 up to 9)
- remainder of the line
need construct a function what get:
- the text in a scalar, and
- the shifting parameter how to shift the number of Bs
for example:
change_ab(2,$text) # and the function will add 2 B
change_ab(-1, $text) #the function will remove one B
EDIT: added some examples - (in the result need to have min 1B or max 9Bs) - in my source code are these conditions, but i forgot write it here (sry))
shifting from result
2 aaaB aaaBBB
3 aaaBB aaaBBBBB
-2 aaaBBBB aaaBB
-3 aaaBB aaaB #min.1
9 aaaBBBB aaaBBBBBBBBB #max.9
my solution is splitting the scalar text into lines. Not very elegant. :(
Exists some better/faster solution - like one big regex without the need of splitting?
Here is my code:
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);
}
the new version based on Zaid's answer:
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: if someone can give a better question title - pls. change it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
让
/e
修饰符为您完成繁重的工作:如果
$b_shift
预计会发生变化,请将操作包装在单个子中:Usage
Output
Let the
/e
modifier do the heavy-lifting for you:If
$b_shift
is expected to vary, wrap the operation in a single sub:Usage
Output
这也应该可以完成这项工作:
当您删除一个“B”时,如上面的代码所示,输出如下:
This should also do the job:
The output when you remove one 'B', as in the code above, is as follows: