为替换预定义一个复杂的替换
Predefining a complex replacement for substitution
我正在尝试使用 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";
那么替换根本不起作用。我感觉 Perl 确实在寻找 "caret parenthesis backslash" 等等,而不是将其解释为正则表达式。
您需要防止插入元字符:
my $regex1 = '^(\w)';
my $regex2 = '"\u"';
(根据@ThisSuitIsBlackNot 的评论更新)
原因是 Perl 插入双引号字符串,所以您的变量 $regex1
和 $regex2
不包含您需要的内容:
my $regex1 = "^(\w)";
my $regex2 = "\u";
print "$regex1\n"; # ^(w)
print "$regex2\n"; # empty line
因此,替换运算符作为 s/^(w)//gee
工作,当然找不到任何东西。
你 真的 不想这样做,因为允许人们将 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";
这就是我去掉你的双引号的原因。 Perl 尝试编译 "^(\w)"
并将 \w
视为它无法识别的转义序列,因此您得到
Unrecognized escape \w passed through
并假设您的意思只是 w
。除非你想像 "^(\w)"
那样转义反斜杠,否则你需要单引号来表示字符串 ^(\w)
类似的情况也适用于 $replacement
。
= "\u$1";
您首先会看到 Perl 试图将 </code> 的当前值插入到双引号字符串中。它目前未定义,所以你得到</p>
<blockquote>
<pre><code>Use of uninitialized value in ucfirst
但即便如此,它还是强制使用空字符串作为 </code>,然后将其大写以供您离开……空字符串</p>
<p>现在你已经设置好了</p>
<pre><code>$regex = '^(w)';
$replacement = '';
所以毫无效果也就不足为奇了
让我们再做一次你的程序,但这次使用单引号,这样就不会搞砸了
use strict;
use warnings 'all';
my $regex = '^(\w)';
my $replacement = '\u';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/g for @array;
print "$_\n" for @array;
现在 $regex
真的是 ^(\w)
而 $replacement
真的是 \u
。会出什么问题?
它工作正常。我们得到
\une two three
\ureen blue red
这正是我们要求的
但现在您的 /e
修饰符派上用场了。 single /e
将 REPLACEMENT
计算为 expression。如果我们想在其中插入 . 'xxx'
或类似的东西,那将很有用,但是由于表达式是 $replacement
我们根本没有任何优势:表达式 $replacement
与插值 $replacement
我们需要另一个 /e
吗?这将在第一个 /e
的结果上调用 eval
,所以我们要求 eval '\u'
,并且不会编译,因为 \u
不是一个可行的 Perl程序,所以 eval
returns undef
我们得到
Use of uninitialized value in substitution iterator
解决办法是把$replacement
做成可编译的程序。在它周围加上双引号,例如 "\u"
将它变成一个非常短的 Perl 程序,其中 returns </code> 的当前值,第一个字符大写 </p>
<p>我们需要将 <code>$replacement
设置为该字符串,包括双引号并避免像以前一样处理转义字符和 </code>。如果我写</p>
<pre><code>my $replacement = '"\u"';
然后我得到了字符串 "\u"
包括双引号
现在让我们试试
use strict;
use warnings 'all';
my $regex = '^(\w)';
my $replacement = '"\u"';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/eeg for @array;
print "$_\n" for @array;
输出
One two three
Green blue red
正如我所说,你真的不想这样做!
我正在尝试使用 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";
那么替换根本不起作用。我感觉 Perl 确实在寻找 "caret parenthesis backslash" 等等,而不是将其解释为正则表达式。
您需要防止插入元字符:
my $regex1 = '^(\w)';
my $regex2 = '"\u"';
(根据@ThisSuitIsBlackNot 的评论更新)
原因是 Perl 插入双引号字符串,所以您的变量 $regex1
和 $regex2
不包含您需要的内容:
my $regex1 = "^(\w)";
my $regex2 = "\u";
print "$regex1\n"; # ^(w)
print "$regex2\n"; # empty line
因此,替换运算符作为 s/^(w)//gee
工作,当然找不到任何东西。
你 真的 不想这样做,因为允许人们将 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";
这就是我去掉你的双引号的原因。 Perl 尝试编译 "^(\w)"
并将 \w
视为它无法识别的转义序列,因此您得到
Unrecognized escape \w passed through
并假设您的意思只是 w
。除非你想像 "^(\w)"
那样转义反斜杠,否则你需要单引号来表示字符串 ^(\w)
类似的情况也适用于 $replacement
。
= "\u$1";
您首先会看到 Perl 试图将 </code> 的当前值插入到双引号字符串中。它目前未定义,所以你得到</p>
<blockquote>
<pre><code>Use of uninitialized value in ucfirst
但即便如此,它还是强制使用空字符串作为 </code>,然后将其大写以供您离开……空字符串</p>
<p>现在你已经设置好了</p>
<pre><code>$regex = '^(w)';
$replacement = '';
所以毫无效果也就不足为奇了
让我们再做一次你的程序,但这次使用单引号,这样就不会搞砸了
use strict;
use warnings 'all';
my $regex = '^(\w)';
my $replacement = '\u';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/g for @array;
print "$_\n" for @array;
现在 $regex
真的是 ^(\w)
而 $replacement
真的是 \u
。会出什么问题?
它工作正常。我们得到
\une two three
\ureen blue red
这正是我们要求的
但现在您的 /e
修饰符派上用场了。 single /e
将 REPLACEMENT
计算为 expression。如果我们想在其中插入 . 'xxx'
或类似的东西,那将很有用,但是由于表达式是 $replacement
我们根本没有任何优势:表达式 $replacement
与插值 $replacement
我们需要另一个 /e
吗?这将在第一个 /e
的结果上调用 eval
,所以我们要求 eval '\u'
,并且不会编译,因为 \u
不是一个可行的 Perl程序,所以 eval
returns undef
我们得到
Use of uninitialized value in substitution iterator
解决办法是把$replacement
做成可编译的程序。在它周围加上双引号,例如 "\u"
将它变成一个非常短的 Perl 程序,其中 returns </code> 的当前值,第一个字符大写 </p>
<p>我们需要将 <code>$replacement
设置为该字符串,包括双引号并避免像以前一样处理转义字符和 </code>。如果我写</p>
<pre><code>my $replacement = '"\u"';
然后我得到了字符串 "\u"
包括双引号
现在让我们试试
use strict;
use warnings 'all';
my $regex = '^(\w)';
my $replacement = '"\u"';
my @array = ('one two three', 'green blue red');
s/$regex/$replacement/eeg for @array;
print "$_\n" for @array;
输出
One two three
Green blue red
正如我所说,你真的不想这样做!