在Perl中,如何仅替换字符串的第一个字符?

在Perl中,如何仅替换字符串的第一个字符?,perl,string,Perl,String,我对Perl一窍不通,必须修复Perl脚本中的一个bug 给定一个包含字符串的变量$myvar,如果第一个字符是点,则将其替换为“foo/bar” 我该怎么做? (如果你能猜到bug,就可以获得额外的积分)一些substrmagic: $_ eq '.' and $_ = "foo/bar" for substr $myvar, 0, 1; 这种语法让我喜欢Perl5.12 for(substr($myvar, 0, 1)) { when('.') { $_ = "foo/bar" }

我对Perl一窍不通,必须修复Perl脚本中的一个bug

给定一个包含字符串的变量
$myvar
,如果第一个字符是点,则将其替换为“foo/bar”

我该怎么做?

(如果你能猜到bug,就可以获得额外的积分)

一些
substr
magic:

$_ eq '.' and $_ = "foo/bar" for substr $myvar, 0, 1;
这种语法让我喜欢Perl5.12

for(substr($myvar, 0, 1)) {
    when('.') { $_ = "foo/bar" }
}
您可以使用:


受@eugene答案讨论的启发,以下是一些在Windows XP上使用ActiveState perl 5.10.1的微型基准测试。当然可以,所以用一匙盐来吃吧

#!/usr/bin/perl

use strict; use warnings;

use Benchmark qw( cmpthese );

my $x = 'x' x 100;
my $y = '.' . $x;

for my $s ($x, $y) {
    printf "%33.33s ...\n\n", $s;
    cmpthese -5, {
        's///' => sub {
            my $z = $s;
            $z =~ s{^\.}{foo/bar};
        },
        'index/substr' => sub {
            my $z = $s;
            if (0 == index $z, '.') {
                substr($z, 0, 1, 'foo/bar');
            }
        },
        'substr/substr' => sub {
            my $z = $s;
            if ('.' eq substr $z, 0, 1) {
                substr($z, 0, 1, 'foo/bar');
            }
        },
    };
    print '=' x 40, "\n";
}
输出:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ... Rate index/substr substr/substr s/// index/substr 1622404/s -- -14% -42% substr/substr 1890621/s 17% -- -32% s/// 2798715/s 73% 48% -- ======================================== .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ... Rate s/// substr/substr index/substr s/// 367767/s -- -57% -62% substr/substr 857083/s 133% -- -10% index/substr 956428/s 160% 12% -- ======================================== XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。。。 速率索引/substr substr/substr s/// 指数/子指数1622404/s--14%-42% substr/substr 1890621/s 17%--32% s///2798715/s 73%48%-- ======================================== .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。。。 速率s///substr/substr索引/substr s///367767/s--57%-62% substr/substr 857083/s 133%--10% 指数/分项指数956428/s 160%12%--

=======================================================================================猜猜这个bug,您描述的修复程序是否足够?如果字符串以“./”开头怎么办?@Benoit:我正在修复的bug@Thilo:在我的情况下不会发生(据我所知),但你是对的,这可能会导致另一个错误。该错误要么是忘记转义模式中的点(因此每个第一个字符都被替换为
“foo/bar”
或忘记锚定模式,以便替换每个点或两者的组合。听起来脚本不是在更改目录,就是在尝试使用相对文件路径,而应该使用绝对路径。在这种情况下,使用正则表达式“修复”文件名不是最好的解决方案--您应该改为使用
File::Spec->catdir
来前置基本目录名,这也将为您规范化文件名。+是可选的正则表达式引号字符,因为普通“/”与“foo/bar”冲突。你可以在这里选择你想要的,我个人认为括号更可读:s{^\.}{foo/bar}。这是替换所有点还是只替换第一个点?只替换字符串最开头的一个点(这是^does)只有第一个。perl正则表达式请参见。^仅在字符串开头匹配。由于加号是正则表达式语法的一部分,因此这似乎是一个糟糕的选择。
\.+
的出现似乎表明正则表达式替换了所有的点,尽管它不替换所有的点。+1是为了可读性。这可能是非perler所能理解的唯一示例。@阿里安:我不这么认为。在作业的LHS上使用substr也是非常完美的…是的,这是不寻常的(对于其他语言的程序员来说),但意图非常明确。+1你在我运行基准测试时进行了编辑;-)在看到结果时,我认为可以使用
index/substr
以及
substr/substr
,因为输入字符串集可能是一个混合体。我整理了我的评论并添加了一个带有基准的CW答案。这是左值substr、别名和智能匹配的一个很好的创造性组合。我喜欢!(而且仍然会使用显而易见且易于理解的regexp替换):-)或者,作为一个例子,说明Perl的所有错误“For”代表循环。如果为了使用其他一些好东西,即使没有循环,也需要使用“for”,那么该语言就被破坏了
for
用于循环。把它塞进这样的东西而不是使用
if
(就像尤金y做的那样)看起来像是纯粹为了聪明一半而进行的混淆。我不需要为
使用
,这只是一个(远程)有趣的选择。@Colin Fine:没有什么比
for
更适合循环
for
用于为某人做某事。试着读它,就像为某事而做某事而且它非常有意义。这同样适用于(某事)做{something}
。Perl不是C、Java或。。。这是表达你自己的语言。它是语言学家创造的语言。
#!/usr/bin/perl

use strict; use warnings;

use Benchmark qw( cmpthese );

my $x = 'x' x 100;
my $y = '.' . $x;

for my $s ($x, $y) {
    printf "%33.33s ...\n\n", $s;
    cmpthese -5, {
        's///' => sub {
            my $z = $s;
            $z =~ s{^\.}{foo/bar};
        },
        'index/substr' => sub {
            my $z = $s;
            if (0 == index $z, '.') {
                substr($z, 0, 1, 'foo/bar');
            }
        },
        'substr/substr' => sub {
            my $z = $s;
            if ('.' eq substr $z, 0, 1) {
                substr($z, 0, 1, 'foo/bar');
            }
        },
    };
    print '=' x 40, "\n";
}
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ... Rate index/substr substr/substr s/// index/substr 1622404/s -- -14% -42% substr/substr 1890621/s 17% -- -32% s/// 2798715/s 73% 48% -- ======================================== .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ... Rate s/// substr/substr index/substr s/// 367767/s -- -57% -62% substr/substr 857083/s 133% -- -10% index/substr 956428/s 160% 12% -- ========================================