So I am wondering if there is a better way of doing the following:
I have an array of lines that I want to print out multiple times and replace certain things differently each time. For example:
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;
}
}
The problem with this being this only works the first time because animals get replaced in the original array. To get around this inside my for loop I just do something like my $line = $sentence;
and then just regex and print $line instead. Is there a better way of doing this?
The r
flag in newer perls can help (5.14 onwards)
The problem is - if you do a "sed style" pattern replace on $sentence
it's an alias to the array element, not a variable in it's own right.
That's because of how array iterators work - it allows you to modify an element in a loop, and have it update the original:
foreach my $value ( @list_of_things ) {
$value++;
}
Will alter @list_of_things
. And this is effectively what your pattern replacement is doing. We need to copy it before we do that, so we can preserve the original - or use the r
flag - to avoid that happening.
So the easiest way is:
#!/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;
}
}
You can probably lose the g
as well, as it appears to be redundant.
Output:
I like most dogs.
Most dogs like me.
I like most cats.
Most cats like me.
But you don't actually need $sentence
any more at all:
foreach my $animal (@animals) {
for (@array) {
print s/animals/$animal/r;
}
}
In older perls, as choroba notes - you can do the same by copying the alias to a local variable:
(my $s = $sentence) =~ s/animals/$animal/g;
print $s;
What you are looking for is a template. Here is an example using 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 });
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.