从 shell 执行“perl 命令”并使用系统命令从 perl 脚本执行相同的命令

从 shell 执行“perl 命令”并使用系统命令从 perl 脚本执行相同的命令

我无法处理特殊字符。

我有以下 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

首先 - 打开strictwarnings在程序顶部:

use strict;
use warnings;

这将帮助您识别错误,例如@core[0]实际上不正确的错误。

然而第二个问题是 - 您将元字符发送到正则表达式 -[]意味着正则表达式中有一些特殊的东西。

所以你真正需要的是quotemeta功能。

print quotemeta '@core[0]';

这将它变成:

\@core\[0\]

或者

print quotemeta $core[0]; 

在您给出的示例中将打印:

TEST\[1\]

当然,您可能也不需要从内部system()调用。这只是低效且混乱的。 perlperl

答案4

在正则表达式中使用\Q以删除字符的特殊含义:

system("perl -pi -e 's/\\Q$core[0]/$core[1]/' $testproc ");

相关内容