我正在尝试使用s///
中的变量。此示例代码按预期工作:
my $regex1 = "e";
my $regex2 = "2";
my @array = ("one two three", "green blue red");
$_ =~ s/$regex1/$regex2/gee foreach (@array);
print $_ foreach (@array);
但是,如果我尝试做一个更复杂的正则表达式,例如:
my $regex1 = "^(\w)";
my $regex2 = "\u$1";
然后替换根本不起作用。我觉得Perl实际上是在寻找“插入符号反斜杠”等等,而不是把它解释为正则表达式。
答案 0 :(得分:1)
您需要阻止元字符的插值:
my $regex1 = '^(\w)';
my $regex2 = '"\u$1"';
(根据@ ThisSuitIsBlackNot的评论更新)
原因是Perl会插入双引号字符串,因此您的变量$regex1
和$regex2
不包含您需要的内容:
my $regex1 = "^(\w)";
my $regex2 = "\u$1";
print "$regex1\n"; # ^(w)
print "$regex2\n"; # empty line
因此,替换运算符作为s/^(w)//gee
工作,当然,找不到任何东西。
答案 1 :(得分:0)
你真的不希望这样做,因为允许人们将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
修饰符很有用。 单 /e
将REPLACEMENT
评估为表达式。如果我们想在那里粘贴$1 . 'xxx'
或类似内容,那将非常有用,但由于表达式为$replacement
,我们根本没有任何优势:表达式$replacement
与插值{{}相同1}}
我们需要另一个$replacement
吗?这会在第一个/e
的结果上调用eval
,因此我们要求/e
,因为eval '\u$1'
不是可行的Perl,所以不会编译程序,\u$1
返回eval
,我们得到
undef
解决方案是将Use of uninitialized value in substitution iterator
转换为可编译程序。在它周围加上双引号,如$replacement
将它变成一个非常短的Perl程序,它返回当前值"\u$1"
,第一个字符是大写的
我们需要将$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;
正如我所说, 真的 不想这样做!