シェルで「perlコマンド」を実行し、システムコマンドを使用してPerlスクリプトで同じコマンドを実行します。

シェルで「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]スクリプトは失敗します。@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]nonで指定する必要があります@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]これは実際に誤ったエラーなどのエラーを識別するのに役立ちます。

しかし、2番目の問題は正規表現にメタ文字を送信することです。これは[]正規表現に特別なものがあることを意味します。

だから本当に必要なのは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 ");

関連情報