http://www.perlmonks.org?node_id=413397

olivierp has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,
While searching for a way to remove the "last" newline in a here-doc, i.e. the one ahead of the end tag, I stumbled across behaviour(s) I do not understand, for which I seek enlightenment
I am probably missing something obvious...
Consider these snippets: (the complete script is at the end of the post)
(my $var1 = <<EOT) =~ s/\r?\n/(munched)/g; First line of "var1" Second line of "var1" has a newline here -> EOT (my $var2 = <<EOT) =~ s/\r?\n\Z/(munched)/; First line of "var2" Second line of "var2" had a newline here -> EOT
Nothing unexpected here. The first replaces every newline, not what I want, and the second is part of what I need.

Now something strange:Fixed following fglock's and Errto's comments.
# Was building $var3 in scalar instead of list context # my $var3 = map { s/\r?\n\Z/(munched)/; $_ } <<EOT; my ($var3) = map { s/\r?\n\Z/(munched)/; $_ } <<EOT; Var also has an interpolated var: $interpolated And the last newline is also absent -> EOT
var3 now contains the "count" of substitutions. I don't understand why,
If I change the above to a here-doc with no interpolated var(s), as here:
my $var4; # This generates "Modification of a read-only value attempted at"; eval { # Still dies, even when in list context. # $var4 = map { s/\r?\n\Z/(munched)/; $_ } <<EOT ($var4) = map { s/\r?\n\Z/(munched)/; $_ } <<EOT var4 has _NO_ interpolated var, and will generate a runtime error EOT }; if ($@){ ($var4 = $@) =~ s/\r?\n\Z//; $@ = undef; print map {s/\r?\n\Z//;$_ }(${^__} =<<EOT); The error generated by \$var4 = map { s/\\r?\\n\\Z/(munched)/; \$_ } <<EOT; is: $var4 EOT }
I get Modification of a read-only value attempted at... Why is $var4's here-doc considered read-only, when the only difference with $var3's is the $interpolated item ?

While I could do with my working snippet, I actually want to do this while creating a HoH. And this is where I stumble again on things I cannot grasp:
# map{}' on the last key is ok. my $href = { key1 => { subkey1 => "Defined first is OK", subkey2 => map{s/\r?\n\Z/(munched)/;$_} (${^__}=<<EOT), First line in sub key. Second line. The third contains an interpolated value, and all is OK. Line 3 $interpolated and no newline here -> EOT }, }; # This explodes... # map{}' ing, then defining another key leads to a runtime error. eval { $href->{key2} = { subkey1 => map{s/\r?\n\Z/(munched)/;$_} ($ {^__}=<<EOT), First line in sub key. Second line. The third contains an interpolated value, and all is OK. Line 3 $var3 and no newline here -> EOT subkey2 => "Kaboom !", }; }; if ($@) { ($href->{key2}->{subkey1} = $@) =~ s/\r?\n\Z//; $href->{key2}->{subkey2} = "Set after eval"; $@ = undef; }
Why is it that using map during the definition of the first key is OK, and if used in another key definition blows up ?
In both cases I do have an interpolated value, and I think that ${^__} is not a read-only value.

Now, let's try with something "cleaner" than map:
# This doesn't die, but gives the count of matches... $href->{key3} = { subkey1 => "Hello", subkey2 => ($ {^__} =<<EOT) =~ s/\r?\n\Z/(munched)/, This works fine, and also strips my ending newline -> EOT subkey3 => "No explosion here...but the count of matches", };
Here again, I get a count of substitutions, and do not understand why.
And finally the las thing I tried, that does what I want:
$href->{key4} = { subkey1 => "Hello", subkey2 => eval { ($ {^__} =<<EOT) =~ s/\r?\n\Z/(munched)/; This works fine, and also strips my ending newline -> EOT return $ {^__}; }, subkey3 => "No explosion here...", };
Would someone kindly explain what I am messing up ?
Update:
To answer why I would map or s/// a here-doc, I am dealing with window's WMI Query language, which does not appreciate having a newline in certain places of its queries. In particular, the condition in a WHERE clause:
WHERE Path='something' is OK.
WHERe Path='
something'
is not.
Complete script here:
use strict; use warnings; my $interpolated = "I was interpolated"; # This strips _every_ newline (my $var1 = <<EOT) =~ s/\r?\n/(munched)/g; First line of "var1" Second line of "var1" has a newline here -> EOT #This only strips the "ending" newline (my $var2 = <<EOT) =~ s/\r?\n\Z/(munched)/; First line of "var2" Second line of "var2" had a newline here -> EOT # This will return the number of substitutions # Fixed. Was building $var3 in scalar instead of list context. #my $var3 = map { s/\r?\n\Z/(munched)/; $_ } <<EOT; my ($var3) = map { s/\r?\n\Z/(munched)/; $_ } <<EOT; Var also has an interpolated var: $interpolated And the last newline is also absent -> EOT my $var4; # This generates "Modification of a read-only value attempted at"; eval { # Still dies, even if called in list context. # $var4 = map { s/\r?\n\Z/(munched)/; $_ } <<EOT; ($var4) = map { s/\r?\n\Z/(munched)/; $_ } <<EOT; var4 also has _NO_ interpolated var, and will generate a runtime error EOT }; if ($@){ ($var4 = $@) =~ s/\r?\n\Z//; $@ = undef; print map {s/\r?\n\Z//;$_ }(${^__} =<<EOT); The error generated by \$var4 = map { s/\\r?\\n\\Z/(munched)/; \$_ } <<EOT; is: $var4 EOT } # map{}' on the last key is ok. my $href = { key1 => { subkey1 => "Defined first is OK", subkey2 => map{s/\r?\n\Z/(munched)/;$_} (${^__}=<<EOT), First line in sub key. Second line. The third contains an interpolated value, and all is OK. Line 3 $interpolated and no newline here -> EOT }, }; # This explodes... # map{}' ing, then defining another key leads to a runtime error. eval { $href->{key2} = { subkey1 => map{s/\r?\n\Z/(munched)/;$_} ($ {^__}=<<EOT), First line in sub key. Second line. The third contains an interpolated value, and all is OK. Line 3 $var3 and no newline here -> EOT subkey2 => "Kaboom !", }; }; if ($@) { ($href->{key2}->{subkey1} = $@) =~ s/\r?\n\Z//; $href->{key2}->{subkey2} = "Set after eval"; $@ = undef; } # This doesn't die, but gives the count of matches... $href->{key3} = { subkey1 => "Hello", subkey2 => ($ {^__} =<<EOT) =~ s/\r?\n\Z/(munched)/, This works fine, and also strips my ending newline -> EOT subkey3 => "No explosion here...but the count of matches abov +e", }; $href->{key4} = { subkey1 => "Hello", subkey2 => eval { ($ {^__} =<<EOT) =~ s/\r?\n\Z/(munched)/; This works fine, and also strips my ending newline -> EOT return $ {^__}; }, subkey3 => "No explosion here...", }; print map {s/\r?\n\Z//; $_} <<EOF; var1 : <$var1> ------ var2 : <$var2> ------ var3 : <$var3> ------ var4 : <$var4> ------ From the hash refs: key1->subkey1 <$href->{key1}->{subkey1}> key1->subkey2 <$href->{key1}->{subkey2}> ------ key2->subkey1 <$href->{key2}->{subkey1}> key2->subkey2 <$href->{key2}->{subkey2}> ------ key3->subkey1 <$href->{key3}->{subkey1}> key3->subkey2 <$href->{key3}->{subkey2}> key3->subkey3 <$href->{key3}->{subkey3}> ----- key4->subkey1 <$href->{key4}->{subkey1}> key4->subkey2 <$href->{key4}->{subkey2}> key4->subkey3 <$href->{key4}->{subkey3}> EOF

--
Olivier