1

I am trying to do a substitution of some variables into a string. The hash contains the data, the $name string is the format. It will put in two of the variable but not the %M one. I am baffled. I have tried two different signal characters and also substitutes with and without spaces. The %M does not go in. ????

use Data::Dumper;

my %Sub = (A=>'Alan',G=>'42', M=>"Memories of Japan");
print "\%Sub=\n".Dumper(%Sub)."\n====\n";

my $name = "#M #A (#G).epub";
print "$name\n====\n";
$name =~ s/(#([AGM]))/($Sub{$2})/eeg;
print "$name\n====\n";

%Sub = (A=>'Bob',G=>'13', M=>'NightHawk');
print "\%Sub=\n".Dumper(%Sub)."\n====\n";
$name = "%M %A (%G).epub";
print "$name\n====\n";
$name =~ s/(%([AGM]))/($Sub{$2})/eeg;
print "$name\n====\n";
  • Never mind... Code is wrong. – Alan Wilson Feb 27 '21 at 07:40
  • `$name =~ s/(%([AGM]))/($Sub{$2})/eeg;` Still won't substitute a string with spaces in it. – Alan Wilson Feb 27 '21 at 07:42
  • That regex is matching either of `A`, `G`, `I` (`[AGI]` character class) -- no `M` ...? – zdim Feb 27 '21 at 07:44
  • Thanks zdim. I caught that late. However, the first one still doesn't work with a string with spaces in it. – Alan Wilson Feb 27 '21 at 07:47
  • Can't write a proper answer now ... (1) no need for `ee` and it can be very dangerous, and here there is no need for even one `e` (2) too many parens ... try this one-liner: `perl -wE'$n = "#M #A (#G)"; say $n; %h = (M => "x", A => "y", G => "z"); $n =~ s/#([AGM])/#$h{$1}/g; say $n'` – zdim Feb 27 '21 at 08:04
  • just in case: the "one-liner" above is entered on the command line and hit Enter. Or, take what is in between `'...'` (that's code that `perl -e` executes) and put it in a file and do `perl file.pl` – zdim Feb 27 '21 at 08:08

2 Answers2

1

You have doubled the "e" modifier at regexpr. Additionally, in this example you can delete it:

use strict;
use warnings;
use Data::Dumper;

my %Sub = (A=>'Alan',G=>'42', M=>"Memories of Japan");
print "\%Sub=\n", Dumper(%Sub), "\n====\n";

my $name = "#M #A (#G).epub";
print "$name\n====\n";
$name =~ s/#([AGM])/$Sub{$1}/g;   #<-- changed
print "$name\n====\n";

%Sub = (A=>'Bob',G=>'13', M=>'NightHawk');
print "\%Sub=\n", Dumper(%Sub), "\n====\n";
$name = "%M %A (%G).epub";
print "$name\n====\n";
$name =~ s/%([AGM])/$Sub{$1}/g;   #<-- changed
print "$name\n====\n";
Miguel Prz
  • 13,718
  • 29
  • 42
1
s/.../($Sub{$2})/eeg

is a shorthand for

s/.../eval( ($Sub{$2}) )/eg    # For each match,
                               # execute eval( ($Sub{$2}) )
                               # and use the value returned.

You're literally asking Perl to compile and execute the value of $Sub{$2} as Perl code, but Memories of Japan is not (normally) valid Perl code.

You want

s/.../$Sub{$2}/eg              # For each match,
                               # execute $Sub{$2}
                               # and use the value returned.

or even

s/.../$Sub{$2}/g               # For each match,
                               # execute qq/$Sub{$2}/
                               # (equivalent to "$Sub{$2}")
                               # and use the value returned.

Note that you should always use use strict; use warnings;. It would have caught the problem of treating NightHawk as Perl code.

ikegami
  • 367,544
  • 15
  • 269
  • 518