Perl通过引用进行循环分配

时间:2016-02-02 14:58:45

标签: perl

所以我想知道是否有更好的方法来做到以下几点:

我有一系列线要多次打印出来,每次都要换一些不同的东西。例如:

my @array = ("I like most animals.\n", "Most animals like me.\n");
my @animals = ("dogs", "cats");
foreach my $animal (@animals) {
    foreach my $sentence (@array) {
        $sentence =~ s/animals/$animal/g;
        print $sentence;
    }
}

这个问题仅在第一次起作用,因为动物在原始阵列中被替换。为了绕过我的for循环,我只需执行类似my $line = $sentence;的操作,然后只使用正则表达式并打印$ line。有没有更好的方法呢?

2 个答案:

答案 0 :(得分:4)

较新的perls中的r标志可以提供帮助(5.14以后)

问题是 - 如果你在$sentence上执行“sed样式”模式替换它是数组元素的别名,而不是它本身的变量。

这是因为数组迭代器的工作原理 - 它允许你修改循环中的元素,并让它更新原始元素:

foreach my $value ( @list_of_things ) { 
    $value++;
}

将改变@list_of_things。这实际上是您的模式替换正在做的事情。我们需要在执行此操作之前复制它,因此我们可以保留原始文件 - 或使用r标记 - 以避免发生这种情况。

所以最简单的方法是:

#!/usr/bin/perl

use warnings;
use strict;

my @array = ("I like most animals.\n", "Most animals like me.\n");
my @animals = ("dogs", "cats");
foreach my $animal (@animals) {
    foreach my $sentence (@array) {
        print $sentence=~ s/animals/$animal/r;
    }
}

你也可能失去g,因为它似乎是多余的。

输出:

I like most dogs.
Most dogs like me.
I like most cats.
Most cats like me.

但你实际上根本不需要$sentence

foreach my $animal (@animals) {
    for (@array) {
        print s/animals/$animal/r;
    }
}

在较旧的perls中,作为choroba注释 - 您可以通过将别名复制到局部变量来执行相同的操作:

(my $s = $sentence) =~ s/animals/$animal/g;
print $s;

答案 1 :(得分:1)

您要找的是一个模板。以下是使用Template的示例:

#!/usr/bin/perl
use warnings;
use strict;

use Template;

my @array = ( "I like most [% animals %].\n",
              "Most [% animals %] like me.\n",
            );
my @animals = qw( dogs cats );

my $template = 'Template'->new;

for my $animal (@animals) {
    for my $sentence (@array) {
        $template->process(\$sentence, { animals => $animal });
    }
}