Reputation: 51
I'm starting to work with perl and I need to edit some text. Sometimes I need that perl read the input line by line and sometimes I need perl read the input as a whole. I know that this can be set with something like:
$/ = undef;
or with something like:
{
local $/;
$myfile= <$MYFILE>;
}
But Im not sure how I have to do if, in the same script, I want to change the reading from "whole" to "line by line" or viceversa. That is, imagine a script with starts as:
use warnings;
use strict;
my $filename = shift;
open F, $filename or die "Usa: $0 FILENAME\n";
while(<F>) {
}
And I make some replaces (s///;). And then I need that go on with my edition but reading as a whole. So I write:
{
local $/;
$filename = <F>;
}
But then I need to go on reading line by line....
Somebody can explain me the logic behind this in order to learn how to 'change' from one mode to another, always keeping the last edited version of the input? Thanks
Ok, sorry. I will try to focus on Y instead of X. For instance, I need to edit a text and make a replacement only on a portion of the text which is delimited by two words. So imagine I want to replace all the forms of "dog" to "cat", but only on those "dogs" which are bewtween the word "hello". My input:
hello
dog
dog
dog
hello
dog
dog
My output:
hello
cat
cat
cat
hello
dog
My script:
use warnings;
use strict;
my $file = shift;
open my $FILE, $file or die "Usa: $0 FILENAME\n";
{
local $/;
$file = <$FILE>;
do {$file =~ s{dog}{cat}g} until
($file =~ m/hello/);
}
print $file;
But I get replaced all "dogs"
I tried other stratagey:
use warnings;
use strict;
my $file = shift;
open my $FILE, $file or die "Usa: $0 FILENAME\n";
{
local $/;
$file = <$FILE>;
while ($file =~ m{hello(.*?)hello}sg) {
my $text = $1;
$text =~ s{dog}{cat}g;
}
}
print $file;
But in this case I get no replacement...
Upvotes: 1
Views: 76
Reputation: 24063
You don't have to resort to slurping and multi-line regexes to solve this. Simply use a variable to track the state of the current line, i.e. whether you're inside or outside your delimiters:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my $in_hello;
while (<DATA>) {
chomp;
$in_hello = ! $in_hello if $_ eq 'hello';
s/dog/cat/ if $in_hello;
say;
}
__DATA__
hello
dog
dog
dog
hello
dog
dog
hello
cat
cat
cat
hello
dog
dog
Upvotes: 2
Reputation: 50647
Default, line by line, mode is back again outside code block:
{
local $/;
$filename = <F>;
}
$/
is global variable which is dynamically scoped in this example.
Upvotes: 1