私はPerlを初めて使用し、次のシナリオで外部コマンド(prg
と呼びます)を実行する方法を知りたいです。
prg
を実行し、そのstdout
のみを取得します。prg
を実行し、そのstderr
のみを取得します。prg
を実行し、そのstdout
とstderr
を別々に取得します。バックティックを使用して外部プログラムを実行し、そのstdout
とstderr
をキャプチャできます。
デフォルトでは、バッククォートはstderr
を破棄し、外部プログラムのstdout
のみを返します。
$output = `cmd`;
プログラムcmdのstdout
をキャプチャし、stderr
を破棄します。
stderr
のみをキャプチャするには、シェルのファイル記述子を次のように使用できます。
$output = `cmd 2>&1 1>/dev/null`;
stdout
とstderr
の両方をキャプチャするには、次のようにします。
$output = `cmd 2>&1`;
上記を使用すると、stderr
とstdout
を区別できなくなります。 stdout
をstderr
から分離するには、両方を別のファイルにリダイレクトし、ファイルを読み取ることができます。
`cmd 1>stdout.txt 2>stderr.txt`;
IPC :: Open または IPC :: Run を使用できます。また、 外部コマンドからSTDERRをキャプチャするにはどうすればよいですか from perlfaq8 をお読みください。
ほとんどの場合、 qx//
演算子(またはバッククォート)。文字列を補間し、シェルで実行するため、リダイレクトを使用できます。
コマンドのSTDOUTをキャプチャするには(STDERRは影響を受けません):
$output = `cmd`;
コマンドのSTDERRとSTDOUTを一緒にキャプチャするには:
$output = `cmd 2>&1`;
コマンドのSTDERRをキャプチャし、そのSTDOUTを破棄するには(ここでは順序付けが重要です)。
$output = `cmd 2>&1 1>/dev/null`;
STDERRをキャプチャするためにコマンドのSTDOUTとSTDERRを交換し、そのSTDOUTを残して古いSTDERRを出力するには:
$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
コマンドのSTDOUTとそのSTDERRの両方を別々に読み取るには、それらを別々にファイルにリダイレクトし、プログラムの完了時にそれらのファイルから読み取るのが最も簡単です。
system("program args 1>program.stdout 2>program.stderr");
上記のEugeneの回答(彼の回答にコメントすることはできません)に注意してください。SDTOUTとSTDERRを交換する構文は、Unix(kshやbashなどのUnixenのようなシェル)では有効ですが、WindowsCMDでは有効ではありません。 (エラー:3>& was unexpected at this time.
)。
WindowsCMDおよびWindows上のPerlでの適切な構文は次のとおりです。
Perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2};
次のコマンドに注意してください。
nslookup 255.255.255.255
sTDOUTで(のような)を生成します:
Server: mymodem.lan
Address: fd37:c01e:a880::1
およびSTDERR:
*** mymodem.lan can't find 255.255.255.255: Non-existent domain
この構文が次のCMD/Perl構文で機能することをテストできます。
最初:
Perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2}; $r=~s/[\n\r]//eg; print qq{on STDOUT qx result=[$r]};"
あなたが得る:Server: mymodem.lan Address: fd37:c01e:a880::1 on STDOUT qx result=[*** mymodem.lan can't find 255.255.255.255: Non-existent domain]
次に
Perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2}; $r=~s/[\n\r]//eg; print STDOUT qq{on STDOUT qx result=[$r]};" 2>&1 1>NUL:
あなたが得る:Server: mymodem.lan Address: fd37:c01e:a880::1
QED [fr:CQFD]
Qxまたはbackticksコマンドの戻り文字列としてstderrとstdoutの両方を取得することはできないことに注意してください。生成されたコマンドによって返されるエラーテキストの長さがN行であることが確実にわかっている場合でも、Eugeneなどが説明するようにSTDERRをSTDOUTにリダイレクトできますが、qxで返されたテキストをスカラー文字列ではなく配列にキャプチャします。 STDERRフローは配列に返されますbefore STDOUTなので、配列の最初のN行はSDTERR行になります。お気に入り:
@r=qx{nslookup 255.255.255.255 2>&1};
$r[0] is "*** mymodem.lan can't find 255.255.255.255: Non-existent domain"
ただし、もちろん、is STDERRおよび厳密にN行(@r[0..N-1]
に格納されている)のエラーテキストがあることを確認する必要があります。 。そうでない場合、唯一の解決策は上記のように一時ファイルを使用することです。