4

Perl スクリプトの途中で、実行したいシステム コマンドがあります。stdin に入力する必要があるデータを含む文字列があり (コマンドは stdin からの入力のみを受け入れます)、stdout に書き込まれた出力をキャプチャする必要があります。Perl でシステム コマンドを実行するさまざまな方法を調べましたが、そのopen機能は必要なもののようですが、両方ではなく stdin または stdout のみをキャプチャできるようです。

現時点では、私の最善の解決策は、を使用しopen、stdout を一時ファイルにリダイレクトし、コマンドの終了後にファイルから読み取ることです。より良い解決策はありますか?

4

9 に答える 9

6

IPC::Open2/3 は問題ありませんが、通常、本当に必要なのはIPC::Run3 だけであることがわかりました。これは、最小限の複雑さで単純なケースを非常にうまく処理します。

use IPC::Run3;    # Exports run3() by default

run3( \@cmd, \$in, \$out, \$err );

ドキュメントでは、IPC::Run3 を他の代替手段と比較しています。使う気がなくても一読の価値あり。

于 2008-09-17T03:41:23.867 に答える
3

perlipc のドキュメントには、IPC::Open2 や IPC::Open3 など、これを行うための多くの方法が記載されています。

于 2008-09-17T02:31:29.463 に答える
3

IPC::Open3 はおそらくあなたが望むことをするでしょう。STDERR と STDOUT をキャプチャできます。

http://metacpan.org/pod/IPC::Open3

于 2008-09-16T22:48:55.457 に答える
3

スクリプトの先頭に、次の行を含めます

use IPC::Open2;

これには、通常、ほとんどの Perl ディストリビューションでデフォルトでインストールされる必要なモジュールが含まれます。(持っていない場合は、CPAN を使用してインストールできます。)次に、open の代わりに、次のように呼び出します。

$pid = open2($cmd_out, $cmd_in, 'some cmd and args');

$cmd_in に送信することでコマンドにデータを送信し、$cmd_out から読み取ることでコマンドの出力を読み取ることができます。

コマンドの stderr ストリームも読み取れるようにしたい場合は、代わりに IPC::Open3 モジュールを使用できます。

于 2008-09-16T23:04:01.287 に答える
2

私が最近見つけたこれを行うための非常に簡単な方法はIPC::Filterモジュールです。それはあなたが非常に直感的に仕事をすることを可能にします:

$output = filter $input, 'somecmd', '--with', 'various=args', '--etc';

リストを渡すと、シェルを経由せずにコマンドを呼び出す方法に注意してください。また、一般的なユーティリティのエラーを適切に処理します。(失敗すると、dieSTDERR からのテキストをエラー メッセージとして使用します。成功すると、STDERR は単に破棄されます。)

もちろん、ストリーミング処理を行う方法がないため、大量のデータには適していません。また、エラー処理が必要に応じて細分化されていない可能性があります。しかし、それは多くの単純なケースを本当に本当に単純にします。

于 2008-09-17T11:36:36.623 に答える
1

IPC::Open2を見てみたいと思います

于 2008-09-16T22:49:23.537 に答える
1

そのための特別なperlコマンドがあります

open2()

詳細については、http ://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html を参照してください。

于 2008-09-16T22:54:19.233 に答える
0

追加のパッケージを含めたくない場合は、次のようにすることができます

open(TMP,">tmpfile");
print TMP  $tmpdata ;
open(RES,"$yourcommand|");
$res = "" ;
while(<RES>){
$res .= $_ ;
}

これはあなたが提案したこととは反対ですが、うまくいくはずです。

于 2008-09-17T08:53:45.767 に答える
0

単一行の出力のみを期待している場合、または結果を改行以外で分割したい場合は、常にこの方法で行います。

my $result = qx( command args 2>&1 );  
my $rc=$?;  
# $rc >> 8 is the exit code of the called program.

if ($rc != 0 ) {  
    error();  
}  

複数行の応答を処理する場合は、結果を配列として取得します。

my @lines = qx( command args 2>&1 );  

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
于 2008-09-16T23:26:16.427 に答える