我正在尝试找到最好的方法来查找和替换(在Ruby 1.9.2中)特殊代码(%x)的所有实例,前面是零或偶数个反斜杠
换句话说,:
%x --> FOO
\%x --> \%x
\\%x --> \\FOO
\\\%x --> \\\%x
\\\\%x --> \\\\FOO
etc.
字符串中可能有多个实例:“这是我的%x字符串,带有两个%x代码。”
在问here和here提出的问题的帮助下,我得到了以下代码来做我想要的事情:
str.gsub(/
(?<!\\) # Not preceded by a single backslash
((?:\\\\)*) # Eat up any sets of double backslashes - match group 1
(%x) # Match the code itself - match group 2
/x,
# Keep the double backslashes (match group 1) then put in the sub
"\\1foo")
然而,正则表达式似乎是重量级的。由于在我的应用程序中将以合理的频率调用此代码,因此我想确保我没有错过更好(更干净/更有效)的方法来执行此操作。
答案 0 :(得分:1)
我可以想象两个可选的正则表达式:
除此之外,我只看到正则表达式的小优化。 “%x”是常量,因此您不必捕获它。 (查找后面-1)
我不确定其中哪一项实际上更有效率。因此,我创建了一个小基准:
$ perl
use strict;
use warnings;
use Benchmark qw(cmpthese);
my $test = '%x \%x \\%x \\\%x \\\\%x \\\\\%x \\\\%x \\\%x \\%x \%x %x';
cmpthese 1_000_000, {
'look-behind-1' => sub { (my $t = $test) =~ s/(?<!\\)((?:\\\\)*)\%x/${1}foo/g },
'look-behind-2' => sub { (my $t = $test) =~ s/(?<!\\)((?:\\\\)*)(\%x)/${1}foo/g },
'alternative' => sub { (my $t = $test) =~ s/((?:^|[^\\])(?:\\\\)*)\%x/${1}foo/g },
};
结果:
Rate alternative look-behind-2 look-behind-1
alternative 145349/s -- -23% -26%
look-behind-2 188324/s 30% -- -5%
look-behind-1 197239/s 36% 5% --
正如您可以清楚地看到的那样,替代正则表达式远远落后于后视方法,并且捕获“%x”比不捕获它略慢。
问候,马蒂亚斯