在Perl代码中改进(优化)现有字符串替换的任何建议?

时间:2011-04-14 23:05:00

标签: regex perl string substitution

Perl 5.8

在现有的Perl脚本中对相当简单的字符串替换的改进。
代码的意图很明确,代码正在运行。

对于给定的字符串,用一个空格替换每个出现的TAB,LF或CR字符,并用两个双引号替换每个双引号。这是现有代码的片段:


# replace all tab, newline and return characters with single space
$val01  =~s/[\t\n\r]/ /g;
$val02  =~s/[\t\n\r]/ /g;
$val03  =~s/[\t\n\r]/ /g;

# escape all double quote characters by replacing with two double quotes
$val01  =~s/"/""/g;
$val02  =~s/"/""/g;
$val03  =~s/"/""/g;

问题:有没有更好的方法来执行这些字符串操作?

通过“更好的方式”,我的意思是更有效地执行它们,避免使用正则表达式(可能使用tr///替换tab,换行符和lf字符),或者可能使用({{1避免重新编译。

注意:我已经考虑将字符串操作操作移动到子例程,以减少正则表达式的重复。

注意:此代码有效,但并未真正破解。我只是想知道是否有更合适的编码约定。

注意:这些操作是在循环中执行的,大量(> 10000)迭代。

注意:此脚本目前在perl v5.8.8下执行。 (该脚本有qr//,但可以更改为require 5.6.0。(安装更高版本的Perl目前不是生产服务器上的选项。)

require 5.8.8

4 个答案:

答案 0 :(得分:3)

您现有的解决方案对我来说很好。

至于避免重新编译,你不必担心。 Perl的正则表达式只按原样编译一次,除非它们包含内插表达式,而不包含内插表达式。

为了完整起见,我应该提一下,即使存在插值表达式,也可以告诉Perl仅通过提供/o标志来编译正则表达式。

$var =~ s/foo/bar/;    # compiles once
$var =~ s/$foo/bar/;   # compiles each time
$var =~ s/$foo/bar/o;  # compiles once, using the value $foo has
                       # the first time the expression is evaluated

答案 1 :(得分:2)

TMTOWTDI

您可以使用trindexsubstrsplit功能作为替代方案。但是,您必须进行测量以确定适合您特定系统的最佳方法。

答案 2 :(得分:2)

您可能过早地进行了优化。您是否尝试使用Devel::NYTProf等分析器查看您的计划花费大部分时间的费用?

答案 3 :(得分:2)

我的猜测是,tr///会比第一个正则表达式中的s///(稍微)快一些。当然,速度要快多少取决于我不了解你的程序和环境的因素。分析和基准测试将回答这个问题。

但是,如果您对代码的任何改进感兴趣,我可以建议可维护性修复吗?您对三个变量运行相同的替换(或替换集)。这意味着当你改变那个替换时,你需要改变它三次 - 做同样的事情三次总是危险的:)

您可以考虑重构代码,使其如下所示:

foreach ($val01, $val02, $val03) {
    s/[\t\n\r]/ /g;
    s/"/""/g;
}

此外,将这些值放在数组中而不是三个类似命名的变量可能是个好主意。

foreach (@vals) {
    s/[\t\n\r]/ /g;
    s/"/""/g;
}