您真的不想这样做,因为允许人们将 Perl 代码传递到您的程序中,这些代码将被提供给eval,这不是一件好事。除了非常复杂之外,它还会让你在没有仔细检查的情况下陷入恶意。如果有人输入了aaa/"unlink *",那么必要的/ee 将删除您当前的文件夹
让我们先弄清楚一些事情。在s/PATTERN/REPLACEMENT/ 中,只有PATTERN 是一个正则表达式。 REPLACEMENT 是一个简单的字符串,就像它在双引号中一样
所以让我们像这样编写你的程序。我已将所有字符串放在单引号中,因为您不想使用转义序列或变量插值。我还将您的 /eeg 修饰符更改为 /g。看起来你在到处喷/e,希望它能起作用,这不是写软件的方法
use strict;
use warnings 'all';
my $regex = 'e';
my $replacement = '2';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/g for @array;
print "$_\n" for @array;
输出
on2 two thr22
gr22n blu2 r2d
现在你想把它改成
my $regex = "^(\w)";
my $replacement = "\u$1";
这就是为什么我把你的双引号扔掉了。 Perl 尝试编译 "^(\w)" 并将 \w 视为它无法识别的转义序列,因此您得到
Unrecognized escape \w passed through
它假定您的意思只是w。除非您想转义像 "^(\\w)" 这样的反斜杠,否则您需要单引号来表示字符串 ^(\w)
$replacement 也有类似的情况。
= "\u$1";
您将看到的第一件事是 Perl 试图将 $1 的当前值插入双引号字符串。它目前是未定义的,所以你得到
Use of uninitialized value $1 in ucfirst
但即便如此,它还是强制使用空字符串作为$1,然后将其大写以留给您......空字符串
现在你已经设置好了
$regex = '^(w)';
$replacement = '';
所以没什么用也就不足为奇了
让我们再次执行您的程序,但这次使用单引号,这样就不会弄乱了
use strict;
use warnings 'all';
my $regex = '^(\w)';
my $replacement = '\u$1';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/g for @array;
print "$_\n" for @array;
现在$regex 真的是^(\w) 而$replacement 真的是\u$1。会出什么问题?
它工作正常。我们得到
\u$1ne two three
\u$1reen blue red
这正是我们所要求的
但现在你的/e 修饰符派上了用场。 single /e 将 REPLACEMENT 评估为 表达式。如果我们想在其中粘贴 $1 . 'xxx' 或类似内容,这将很有用,但由于表达式是 $replacement,我们根本没有优势:表达式 $replacement 与插值 $replacement 相同
我们需要另一个/e 吗?这将在第一个/e 的结果上调用eval,所以我们要求eval '\u$1',由于\u$1 不是一个可行的Perl 程序,所以eval 返回@ 987654363@,我们得到
Use of uninitialized value in substitution iterator
解决办法是把$replacement做成一个可编译的程序。在它周围加上双引号,比如 "\u$1" 将它变成一个非常短的 Perl 程序,它返回 $1 的当前值,第一个字符大写
我们需要将$replacement 设置为该字符串,包括双引号并避免像以前一样处理转义字符和$1。如果我写
my $replacement = '"\u$1"';
然后我得到确切的字符串"\u$1",包括双引号
现在让我们试试
use strict;
use warnings 'all';
my $regex = '^(\w)';
my $replacement = '"\u$1"';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/eeg for @array;
print "$_\n" for @array;
输出
One two three
Green blue red
正如我所说,你真的不想这样做!