文字列をバッククォートでクォートする
[Perlop の翻訳です]
必要なら /bin/sh
、または、それに相当するものを通して、システムコマンドとして展開そして実行される文字列です。
シェルのワイルドカード、パイプ、リダイレクションは有効です。
system
と同様に、文字列にシェルのメタキャラクタが含まれていなければ、
直接的に実行します。
コマンドの標準出力は収集され、それが返されます。標準エラーは影響を受けません。
スカラーコンテキストでは、一つの文字列(複数行の可能性あり)として返されます。
シェル(またはコマンド)が開始されなかった場合は undef
が返されます。
リストコンテキストでは、行のリストが返されます($/
または $INPUT_RECORD_SEPARATOR
で行を定義したとしても)。
シェル(またはコマンド)が開始されなかった場合は空のリストが返されます。
バックティックは標準エラーに影響を及ぼさないため、もしこれを解決したいなら、 シェルのファイル・ディスクリプタ構文(シェルがそれをサポートしていると仮定)を使ってください。 コマンドの STDERR と STDOUT を一緒に取り出したいなら次のようにしてください:
$output = `cmd 2>&1`;
コマンドの STDOUT は取り出したいけれども、STDERR は捨ててもよいなら次のようにします。
$output = `cmd 2>/dev/null`;
コマンドの 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");
コマンドによって使われる STDIN ファイルハンドルは Perl の STDIN から継承されます。
open(SPLAT, "stuff") || die "can't open stuff: $!";
open(STDIN, "<&SPLAT") || die "can't dupe SPLAT: $!";
print STDOUT `sort`;
上記コードは "stuff" という名前のファイルのコンテンツをソートしてそれを出力します。
区切り文字にシングルクォーテーションを使うと、それをシェルにそのまま引き渡すことで、 Perl のダブルクォーテーションによる展開からコマンドを守ります。
$perl_info = qx(ps $$); # これは Perl の $$
$shell_info = qx'ps $$'; # これは新たなシェルの $$
文字列がどのように評価されるのかは、完全にシステムのコマンドインタプリタ次第です。
ほとんどのプラットフォームでは、コマンドを文字通りに扱ってほしいならシェルのメタキャラクタを守らなければいけません。
とはいえ、どの文字をどのようにエスケープするのかがはっきりしないため、実際にそうするのは難しいです。
バックティックは fork()
と
exec()
を使えばエミュレートできますが、
その分かりやすくて安全な例は
perlsec をご覧ください。
プラットフォームによっては(特に DOS 系)、シェルは複数行コマンドを扱うことができないかもしれません。
そのため、文字列に改行を入れてしまうと、期待通りに動作しないかもしれません。
もしシェルがサポートしていれば、複数行のコマンドを、コマンド区切り文字で行を区切って単一の行にしてから評価できるかもしれません
(たとえば、多くの UNIX シェルでは ;
が、Windows NT の cmd
シェルなら &
がコマンド区切り文字になります)。
コマンドシェルによっては、コマンドラインの長さに制限があるかもしれない点に注意してください。 すべての展開が終わった後の文字列がこの制限を超えないようにしないといけません。 特定の環境に関しての詳細は、プラットフォームごとのリリースノートを参照してください。
この演算子を使うと、プログラムをポーティングするのが難しくなります。
それは、呼び出されるシェルコマンドはシステムごとに違うことに加え、
実際にはまったく存在しないかもしれないからです。
一つの例としては、POSIX シェルの type
コマンドは、
DOS の type
コマンドとはまったく別物です。
これは、何かを成し遂げるのにバックティックが最も効果的な方法なのに、
無理をしてバックティックを避けるべきということではありません。
Perl はグルー言語として作られたのです。そして、結びつけるものの一つがコマンドなのです。
あなたが何に陥っているのかをよく理解してください。
system
のように、バックティックは子プロセスの exit コードを
$?
にセットします。
もし失敗を自分自身で調査したいなら、次のように $?
を調べてすべての可能性のある失敗モードをチェックすることができます。
if ($? == -1) {
print "failed to execute: $!\n";
}
elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
printf "child exited with value %d\n", $? >> 8;
}
コマンドの出力を読み取るときに使われる I/O レイヤを制御したいなら、 open プラグマを使ってください。
use open IN => ":encoding(UTF-8)";
my $x = `cmd-producing-utf-8`;
qx//
は readpipe
を使って関数のように呼び出すこともできます。
詳細は "I/O Operators" を参照してください。