我有Perl代码:如何用Perl执行多个替换?
my $s = "The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog";
我想替换每个+
空间和dog
与cat
。
我有这样的正则表达式:
$s =~ s/\+(.*)dog/ ${1}cat/g;
但是,这只是+
和最后dog
第一次出现的匹配。
我有Perl代码:如何用Perl执行多个替换?
my $s = "The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog";
我想替换每个+
空间和dog
与cat
。
我有这样的正则表达式:
$s =~ s/\+(.*)dog/ ${1}cat/g;
但是,这只是+
和最后dog
第一次出现的匹配。
可以使用“E”改性剂在s///
表达式的第二部分来执行代码。
$s =~ s/(\+)|(dog)/$1 ? ' ' : 'cat'/eg;
如果$1
为真,则表示匹配\+
,所以它替换的空间;否则它会替代“猫”。
为什么打扰捕捉狗? – 2010-05-05 18:51:27
这个解决方案效果很好,但是当我运行配置文件时,似乎两条线比一条线工作得更快,因为它必须调用CORE:substcont而不仅仅是CORE:subst。但无论如何非常感谢你 我已经有两行解决方案。发生什么事是我有一个文件与100K行的字符串,我将需要在插入到数据库之前进行标准化。我正在努力加快速度。如果我跑过正则表达式比赛的话,我会感到印象不够 – user332951 2010-05-05 19:22:55
乍得:为了防止它在邻近区域内散乱跑? :)没错,不需要捕捉“狗”。 '$ s =〜s /(\ +)| dog/$ 1? '':'cat'/ eg;' – Brock 2010-05-05 22:49:29
答案很简单 - 使用2线!:
$s =~ s/+/ /g;
$s =~ s/dog/cat/g;
它很可能在一个行完成与“非贪婪”匹配,但是这应该做的伎俩
两个正则表达式可能使你的生活轻松了许多:
$s =~ s/\+/ /g;
$s =~ s/dog/cat/g;
下面的比赛“+”,后面一堆东西,其次是“狗”。另外,“+”在技术上是一个元字符。
/+(.*)dog/
我已经有两行解决方案。发生什么事是我有一个文件与100K行的字符串,我将需要在插入到数据库之前进行标准化。我正在努力加快速度。如果我跑过正则表达式匹配,我会感到印象不够,如果我必须这样做两次 – user332951 2010-05-05 18:07:51
考虑到下面的新答案之一,这似乎是错误的印象。 – 2010-05-05 18:37:40
@Mark谢谢;我评论了这个问题。 – WhirlWind 2010-05-05 20:11:10
散列可以做你想做的:
#!/usr/bin/perl
use strict;
use warnings;
my $s = "The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog";
my %replace = (
"+" => " ",
dog => "cat",
);
$s =~ s/([+]|dog)/$replace{$1}/g;
print "$s\n";
在我看到你所关心的性能的意见,这两个正则表达式的解决方案是更好的性能。这是因为任何适用于一个正则表达式的解决方案都需要使用捕获(这会减慢正则表达式)。
这里有一个基准的结果:
eval: The quick brown fox jumps over the lazy cat that is my cat
hash: The quick brown fox jumps over the lazy cat that is my cat
two: The quick brown fox jumps over the lazy cat that is my cat
Rate hash eval two
hash 33184/s -- -29% -80%
eval 46419/s 40% -- -72%
two 165414/s 398% 256% --
我用下面的基准:
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark;
my $s = "The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog";
my %replace = (
"+" => " ",
dog => "cat",
);
my %subs = (
hash => sub {
(my $t = $s) =~ s/([+]|dog)/$replace{$1}/g;
return $t;
},
two => sub {
(my $t = $s) =~ s/[+]/ /g;
$t =~ s/dog/cat/g;
return $t;
},
eval => sub {
(my $t = $s) =~ s/(\+)|(dog)/$1 ? ' ' : 'cat'/eg;
return $t;
},
);
for my $k (sort keys %subs) {
print "$k: ", $subs{$k}(), "\n";
}
Benchmark::cmpthese -1, \%subs;
如果速度是重要的,你应该有两行坚持。但是,当我需要立即执行多个替换时,我通常更关心便利性,所以我使用Chas所建议的散列。欧文斯。与双线相比,两个优点是易于修改,并且其行为与预期相同(例如,当“猫”替代“猫”时,“猫”替代)。
然而,我感到非常懒手工编写的正则表达式,喜欢组装它与加盟,并使用地图逃避的东西:
#!/usr/bin/perl
use strict;
use warnings;
my $s = "The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog";
my %replace = (
"+" => " ",
dog => "cat",
);
my $regex = join "|",
#use quotemeta to escape special characters
map { quotemeta }
#reverse sort the keys because "ab" =~ /(a|ab)/ returns "a"
sort { $b cmp $a } keys %replace;
#compiling the regex before using it prevents
#you from having to recompile it each time
$regex = qr/$regex/;
$s =~ s/($regex)/$replace{$1}/g;
print "$s\n";
我自己更喜欢代码重复性和方便性,但是对于这样的特殊情况,我必须读取字符串,每隔3分钟从100k到1Mils的范围内读取字符串。因此,我不得不担心速度或事情会在队列中堵塞 – user332951 2010-05-05 21:02:04
Chas:感谢您的更正。我只用了几天的计算器,我已经在学习有用的东西了。我应该去寻找我可能使用过这种代码的地方......只有一个问题,为什么不是s/$ regex/$ replace {$&}/g? – Pontus 2010-05-08 15:06:15
duenguyen:听起来很有趣!来自perldoc(http://perldoc.perl.org/perlvar.html#%24%26)的 – Pontus 2010-05-08 15:07:45
Perl的5.14和更新与能力链换人一个非破坏性的任务,所以你可以用一块石头杀死3只鸟:做你的两个全局替换,并将结果赋给一个新的变量而不修改你的原始变量。
my $s = "The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog";
my $result = $s =~ s/+/ /gr
=~ s/dog/cat/gr;
将取代所有的+
空间和与cat
替换每dog
,将结果分配到一个新的变量。在一个班轮。
这难道不是简化的东西,为此使用两个单独的正则表达式替换吗? – WhirlWind 2010-05-05 00:42:15
请问真正的问题? – codeholic 2010-05-05 05:25:34
如果你正在寻找性能,你应该问你的问题,但获得性能的方式可能是完全没有正则表达式。例如,你试过tr吗? – WhirlWind 2010-05-05 20:09:31