2016-04-20 10 views
0

は、私はファイルハンドル開くために、コードを次していると仮定します。私はcommand1が出力command2がうまく扱うことができないことが分かっ

open my $fh, "command1 | command2 |"; 

をので、私はそれらに対処するためにcommand1command2間perlのフィルタを挿入しようとしています:

use Config; 
open my $fh, "command1 | $Config{perlpath} -ple 'blah blah' | command2 |"; 

私の質問は以下のとおりです。

  1. が、それはOKを使用することですシステムコールで直接?
  2. 自分のperlバイナリーを呼び出すのは難しいですね。もっと良い解決策はありますか?

おかげ

+1

'$ CONFIG {perlpath}'の短いバージョン:[ '$^X '(https://でmetacpan。org/pod/perlvar#EXECUTABLE_NAME) – mob

+0

確かに罪です。しかし、マイナーなもの。 – mob

答えて

1

それが直接システムコールで$ CONFIG {perlpath}を使用してOKですか?比較的

。これはコードの残りの部分と同じくらい移植性があります(これはすでにunix-ishで動作することに依存しています)。セキュリティ上の心配がありますが、その変数の価値に影響を与える可能性のある人がすでに大混乱の原因になっているため、非常に大きなものではないと言いたいと思います。おそらくそれに関しては$^Xが安全でしょう。安全のためにパイプラインの途中でシェルをバイパスすることはできないので、String::ShellQuoteを使用して引用符を付けるとよいでしょう。自分のperlのバイナリを呼び出す

はナッツと思われます。もっと良い解決策はありますか?

は、 "より良い" のあなたの定義に依存します。 「元のperlプロセスでの出力command2にそれを渡し、そしてcommand2読み」の両方command1command2別途、プロセスを実行するcommand1の出力をすることです周りの別の方法は、間違いなくあります。しかし、どのようにそれを行うか注意する必要があります。 2つの安全な方法があります。

最初の方法は簡単ですが、より多くの時間とメモリが必要です。最初にcommand1を実行し、すべての出力を文字列に読み込んで処理し、バッファされた出力を入力として提供します。command2これを行う最善の方法は、command2の入力と出力を処理するためにIPC::Runを使用することです(一貫性のためだけに両方のコマンドを使用してください)。 command2の入力ハンドルにすべてのデータを印刷し、すべての出力を読み取るとデッドロックすることができますが、IPC :: Runは必要に応じて読み書きをインタリーブし、簡単なインターフェイスを提供します。

第二の方法は、より複雑なものの、元の動作に近いです:あなたは、プロセスの構築のためにそのクラスを使用して、IO::AsyncまたはPOEのような非同期フレームワークのいくつかの種類を必要とし、それらの間の通信にハンドラを設定、あなたのフィルタリングを行います、出力を集める。

Here's親のperlプロセスで実行されているパイプラインの中間部分を除いて、ls | perl -pe '$_ = uc' | revに相当するテスト済みのおもちゃの例です。あなたはそれを使用することはできませんが、それは説明する価値があると思いました。

関連する問題