Perlのバックティック、システム、execの違いは何ですか?


237

誰かが私を助けてくれますか?Perlでは、以下の違いは何ですか?

exec "command";

そして

system("command");

そして

print `command`;

シェルコマンドを実行する他の方法はありますか?


8
stackoverflow.com/questions/797127/…のほぼ正確な複製です。ただし、この1つにはexecがあり、もう1つにはパイプがあります。
マイケルマイヤーズ

回答:


268

エグゼクティブ

コマンドを実行し、決して戻りませんreturn関数のステートメントのようなものです。

コマンドが見つからない場合execはfalseを返します。コマンドが見つかるとまったく返されないため、trueは返されません。コマンドのSTDOUTSTDERRまたは終了ステータスを返す意味もありません。perlfuncこれは関数なので、ドキュメント はにあります。

システム

コマンドを実行し、コマンドが終了した後、Perlスクリプトが続行されます。

戻り値はコマンドの終了ステータスです。これに関するドキュメントはにあり perlfuncます。

バックティック

like systemはコマンドを実行し、コマンドが終了した後もperlスクリプトが続行されます。

system戻り値とは逆にSTDOUTコマンドのです。 qx//バックティックと同じです。あなたはそれについてのドキュメントを見つけることができるperlopとは違っているため、systemそしてexecそれが演算子です。


他の方法

上記に欠けているのは、コマンドを非同期で実行する方法です。つまり、perlスクリプトとコマンドが同時に実行されます。これはopen。コマンドの読み取りSTDOUT/ STDERR書き込みができますSTDIN。ただし、プラットフォームに依存します。

このタスクを容易にすることができるいくつかのモジュールもあります。ありIPC::Open2IPC::Open3そしてIPC::RunWin32::Process::Create、Windows を使用している場合も同様 です。


1
私はあなたがs / perlcunc / perlfunc /を意味していると思います...また、perlipcのドキュメントはパイプを開くことについて深く掘り下げています。
ephemient 2009

7
perlcunc、多分これは私の新しいニックネームになるでしょう;-)
Ludwig Weinzierl

8
記録のために、バックティックとqx []も$?に入力します。(OSの戻り値)。
jjohn 2013年

167

一般的なIの使用ではsystemopenIPC::Open2、またはIPC::Open3私が何をしたいかによって異なります。qx//オペレータは、シンプルながら、あまりにも迅速なハックの非常に便利な外であることをその機能に制約されます。私が見つけるopenずっと手軽に。

system:コマンドを実行し、コマンドが戻るのを待ちます

systemコマンドを実行し、その出力を気にせず、コマンドが完了するまでPerlスクリプトに何もさせたくない場合に使用します。

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

または

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx//または ``:コマンドを実行してそのSTDOUTをキャプチャします

qx//コマンドを実行し、STDOUTに書き込む内容をキャプチャし、コマンドが完了するまでPerlスクリプトが何もしないようにする場合に使用します。

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

exec:現在のプロセスを別のプロセスに置き換えます。

コマンドを実行し、その出力を気にせず、コマンドが戻るのを待ちたくない場合に、とexec一緒forkに使用します。 system本当に

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

waitpidおよびのperlipcマニュアルを読むこともできます。

open:プロセスを実行し、そのSTDINまたはSTDERRへのパイプを作成します

openプロセスのSTDINにデータを書き込んだり、プロセスのSTDOUTからデータを読み取ったりしたい場合に使用します(ただし、両方を同時にはできません)。

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC :: Open2:プロセスを実行し、STDINとSTDOUTの両方へのパイプを作成します

IPC::Open2プロセスのSTDINおよびSTDOUTを読み書きする必要がある場合に使用します。

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC :: Open3:プロセスを実行し、STDIN、STDOUT、およびSTDERRへのパイプを作成します

IPC::Open3プロセスの3つの標準ファイルハンドルをすべてキャプチャする必要がある場合に使用します。例を書きますが、IPC :: Open2とほとんど同じように機能しますが、引数と3番目のファイルハンドルの順序が少し異なります。


非常に有益で最新の答え。ありがとう@ chas-owens
Jassi

IPC :: Open3は、ほとんどの用途にとって低すぎるレベルです。IPC :: Run3とIPC :: Runは通常、はるかに適切です。
池上2016

17

最初にマニュアルを引用させてください:

perldoc exec()

exec関数はシステムコマンドを実行して戻りません - 戻りたい場合は、execではなくsystemを使用してください

perldoc system()

最初にforkが実行され、親プロセスが子プロセスの完了を待機することを除いて exec LISTとまったく同じことを行います。

execおよびsystemとは対照的に、バックティックは戻り値を提供しませんが、収集されたSTDOUTを提供します。

perldoc `文字列`

(おそらく)補間され、/ bin / shまたは同等のコマンドを使用してシステムコマンドとして実行される文字列。シェルのワイルドカード、パイプ、リダイレクトが優先されます。収集されたコマンドの標準出力が返されます。標準エラーは影響を受けません。


代替案:

STDOUT、STDERR、または戻りコードをフェッチするより複雑なシナリオでは、IPC :: Open2IPC :: Open3などのよく知られた標準モジュールを使用できます。

例:

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

最後に、CPANからのIPC :: Runも一見の価値があります…


3
これは失礼な反応です。あなたは怒ることなく助けようとするべきです。
シェーンC.メイソン

1
彼は昔のRTFM:P
v3を

誤解を避けるために、実際には失礼なことを意味していませんでした;)ただし、fワードを削除しました…
Benedikt Waldvogel 2009

2
私は確かにそれを失礼なものとして解釈しませんでした。たぶん、ブルスクだが、これは思慮深い答えを必要とする高度にインテリジェントな質問ではない。

11

Perlのバッククォート(の違いは何だ`)、systemとはexec

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

execコマンドを実行し、Perlスクリプトを再開することはありません。これreturnは、ステートメントが関数に対するスクリプトのようなものです。

コマンドが見つからない場合は、execfalseを返します。コマンドが見つかると、まったく返らないため、trueを返すことはありません。コマンドのSTDOUTSTDERRまたは終了ステータスを返す意味もありません。これは関数なので、perlfuncでドキュメントを見つけることができます。

例えば:

#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

上記のコードには3つのprintステートメントがありますがexec、スクリプトを終了するため、最初の印刷ステートメントのみが実行されます。また、execコマンド出力はどの変数にも割り当てられていません。

ここでは、最初のprintステートメントの出力を取得し、ls標準出力でコマンドを実行するだけです。

system

systemコマンドを実行し、コマンドが終了するとPerlスクリプトが再開されます。戻り値はコマンドの終了ステータスです。これに関するドキュメントはperlfuncにあります。

例えば:

#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

上記のコードには、3つのprintステートメントがあります。systemコマンドの後にスクリプトが再開されると、3つの印刷ステートメントすべてが実行されます。

また、実行結果system はに割り当てdata2られますが、割り当てられた値は0(からの終了コードls)です。

ここでは、最初のprintステートメントの出力、次にlsコマンドの出力、続いprintて標準出力の最後の2つのステートメントの出力を取得しています。

バックティック(`

のようsystemに、コマンドをバッククォートで囲むとそのコマンドが実行され、コマンドが終了するとPerlスクリプトが再開されます。とは対照的にsystem、戻り値はSTDOUTコマンドのものです。qx//バックティックと同じです。システムおよびとは異なり、これはオペレーターであるため、perlopでそれに関するドキュメントを見つけることができますexec

例えば:

#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

上記のコードには3つのprintステートメントがあり、3つすべてが実行されています。の出力はls直接標準出力に送られるのではなく、変数に割り当てられdata2、最後の印刷ステートメントによって印刷されます。


例を挙げた最良の説明。どうもありがとう。
Arslan Anwar、

2

「exec」と「system」の違いは、execが現在のプログラムを「command」に置き換え、決してプログラムに戻らないことです。一方、システムは、「コマンド」をフォークして実行し、実行が完了すると「コマンド」の終了ステータスを返します。バックティックは「コマンド」を実行し、標準出力を表す文字列を返します(画面に出力されたものは何でも)。

popenを使用してシェルコマンドを実行することもできます。シェルモジュール-一般的なシェルコマンドへの透過的なアクセスを提供する 'use shell'があると思います。

それがあなたのためにそれを明らかにすることを願っています。


もしかしてuse Shell;search.cpan.org/dist/Shell/Shell.pm)?それは広くインストールされておらず、質問にも当てはまらないと思います...
ephemient

1
彼の質問の最後の部分は、「シェルコマンドを実行する他の方法もあるか」というものでした。シェルは、シェルコマンドを実行するもう1つの方法です。
シェーンC.メイソン

2
ドキュメントには、「このパッケージはいくつかのPerl機能を示すショーケースとして含まれています。本番プログラムには使用しないでください。任意のコマンドの標準出力を取得するためのシンプルなインターフェースを提供しますが、必要なものを達成する方法。」
Chas。オーエンス

2
再び、「他の方法はあるか」という彼の質問に答えました
シェーンC.メイソン

悪い、サポートされていない方法は、それらが悪い、サポートされていないという警告なしに与えられるべきではありません。
Chas。オーエンス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.