我无法处理特殊字符。
我有以下 perl 脚本。
while(@mapping_array[$i])
{
chomp(@mapping_array[$i]);
my @core= split ( / / , $mapping_array[$i]) ;
@core[0] =~ tr/ //ds ; ## Deleting blank spaces
@core[1] =~ tr/ //ds ;
system("perl -pi -e 's/@core[0]/@core[1]/' $testproc ");
print "@core[0] \n";
print "@core[1] \n";
$i++;
}
问题是我的@core[0]
变量可能是一个简单的字符串(例如)abc
或更复杂的字符串(例如)TEST[1]
。我的脚本按预期工作abc
,将其替换为 的值@core[1]
,但如果 my@core[0]
是 ,则脚本会失败TEST[1]
。
在替换运算符中使用?
而不是没有帮助。/
我怎样才能正确地做到这一点?
答案1
听起来你正在寻找quotemeta
。正如中所解释的perldoc -f quotemeta
:
quotemeta EXPR
Returns the value of EXPR with all the ASCII non-"word" characters
backslashed. (That is, all ASCII characters not matching
"/[A-Za-z_0-9]/" will be preceded by a backslash in the returned
string, regardless of any locale settings.) This is the internal
function implementing the "\Q" escape in double-quoted strings.
因此,您的脚本将是(请注意,数组元素应指定为$foo[N]
,而不是@foo[N]
):
chomp(@mapping_array);
while($mapping_array[$i])
{
my @core= split ( / / , $mapping_array[$i]) ;
$core[0] =~ tr/ //ds ; ## // Deleting blank spaces
$core[1] =~ tr/ //ds ; # / fix SO highlighting
my($k,$l)=(quotemeta($core[0]),quotemeta($core[1]))
system("perl -pi -e 's/$k/$l/' $testproc ");
print "$core[0] \n$core[1] \n";
$i++;
}
答案2
通常可以避免从 Perl 运行 Perl。
for my $both (@mapping) {
my ($regex, $replace) = split / /, $both;
tr/ //ds for $regex, $replace; # // Fix SO highlighting bug.
open my $IN, '<', $testproc or die $!;
open my $OUT, '>', "$testproc.new" or die $!;
while (<$IN>) {
s/\Q$regex/$replace/;
print {$OUT} $_;
}
close $OUT or die $!;
rename $testproc, "$testproc.old" or die $!;
rename "$testproc.new", $testproc or die $!;
}
\Q 对应于引用元这会阻止解释 $regex 变量中的特殊字符。
答案3
首先 - 打开strict
并warnings
在程序顶部:
use strict;
use warnings;
这将帮助您识别错误,例如@core[0]
实际上不正确的错误。
然而第二个问题是 - 您将元字符发送到正则表达式 -[]
意味着正则表达式中有一些特殊的东西。
所以你真正需要的是quotemeta
功能。
print quotemeta '@core[0]';
这将它变成:
\@core\[0\]
或者
print quotemeta $core[0];
在您给出的示例中将打印:
TEST\[1\]
当然,您可能也不需要从内部system()
调用。这只是低效且混乱的。 perl
perl
答案4
在正则表达式中使用\Q
以删除字符的特殊含义:
system("perl -pi -e 's/\\Q$core[0]/$core[1]/' $testproc ");