1

ここで見たこのコマンドを実行したい:

diff  <(echo "string1" ) <(echo "string2")

perlから、試しましたsystem

system('diff  <(echo "string1" ) <(echo "string2")');

しかし、それが原因です:

sh: 1: Syntax error: "(" unexpected

誰でもトリックを知っていますか?

さらに、エスケープが必要な 2 つの変数から読み取られたときに、この種のコマンドを安全に実行するにはどうすればよいでしょうかstring1string2

4

3 に答える 3

4

bash を使用してコマンドを実行する

system('/bin/bash -c \'diff  <(echo "string1" ) <(echo "string2")\'');

デフォルトでは、システムは /bin/sh を使用してコマンドを実行しますが、/bin/sh は機能「()」をサポートしていません。

安全に実行するには、キー文字をエスケープする必要があります。引用はこちら。

バグコード:

my $var1 = "\"string1;ls";
my $var2 = "\"string2;ls";
my $cmd = "diff <(echo \"$var1\") <(echo \"$var2\" )";
print $cmd . "\n";
my @args = ("bash", "-c", $cmd);
system(@args);
print "=======" . "\n";

セーフ コード:

$var1 = "\"string1;ls";
$var2 = "\"string2;ls";
$var1 =~ s/(\")/\\$1/g;
$var2 =~ s/(\")/\\$1/g;
$cmd = "diff <(echo \"$var1\") <(echo \"$var2\" )";
print $cmd . "\n";
@args = ("bash", "-c", $cmd);
system(@args);
于 2012-12-27T14:26:32.743 に答える
1

(あなたが望むように)スペースを処理しない場合でも、これを修正しています。最初の文字を引用しません。私はそれをより賢くしたので、明白なものを引用しません。

# this will escape all the characters in the string  
my $str = '/?\abc"';
( my $str3 = $str) =~ s/([^a-zA-Z0-9])/\\\1/g;

printf ("%s\n",$str);
printf ("%s\n",$str3);

my @args = ( "bash", "-c", 'diff <(echo "$foo" ) <(echo "string2")' );

system(@args);
于 2012-12-27T14:14:15.107 に答える
0

シェルのない (ただし移植性が低い可能性がある) バージョン:

#!perl
use strict;
use warnings;
use Fcntl;

open my $one, '-|', 'echo', 'string1' or die "$! opening first input";
fcntl $one, F_SETFD, (fcntl($one, F_GETFD, 0) & ~FD_CLOEXEC)
  or die "$! keeping open first input";
open my $two, '-|', 'echo', 'string2' or die "$! opening second input";
fcntl $two, F_SETFD, (fcntl($two, F_GETFD, 0) & ~FD_CLOEXEC)
  or die "$! keeping open second input";

open my $diff, '-|', 'diff', "/dev/fd/".fileno($one), "/dev/fd/".fileno($two)
  or die "$! running diff";

while (<$diff>) {
    print;
}

これは基本的にシェルが行うこととまったく同じです (最初の「echo」コマンドのサブプロセスを開き、2 番目の「echo」コマンドのサブプロセスを開き、子プロセスがファイルハンドルを継承できるようにし、「diff」へのサブプロセスを開きます)。その引数は、開いているファイルハンドルを指す特別なファイル名です)。唯一の違いは、diff が画面に出力できるようにするのではなく、出力をキャプチャして自分で出力することです。

新しいバージョン (/bin/echo なし、エスケープなし、デッドロックなし)

#!/usr/bin/perl
use strict;
use warnings;
use Fcntl;

my $pid_one = open my $one, '-|';
die "$! opening first input" unless defined $pid_one;
if (!$pid_one) { # child
    print "string1\n";
    exit;
}
fcntl $one, F_SETFD, (fcntl($one, F_GETFD, 0) & ~FD_CLOEXEC)
  or die "$! keeping open first input";

my $pid_two = open my $two, '-|';
die "$! opening second input" unless defined $pid_two;
if (!$pid_two) { # child
    print "string2\n";
    exit;
}
fcntl $two, F_SETFD, (fcntl($one, F_GETFD, 0) & ~FD_CLOEXEC)
   or die "$! keeping open second input";

 open my $diff, '-|', 'diff', "/dev/fd/".fileno($one), "/dev/fd/".fileno($two)
  or die "$! running diff";
 while (<$diff>) {
    print;
}

string1親プロセスの変数やstring2他のコマンドの出力など、何でもかまいません。

于 2012-12-27T15:35:24.590 に答える