重要:コマンドが失敗したかどうかを判断するには、Perlの関数からの戻り値を常に確認する必要があります。system
以下のコードのように、Perlを使用sprintf
してfloat値をフォーマットします。はい、フォーマット指定子としてコマンドを使用することで逃げることができるかもしれませんが、コマンドが他の場所に迷子の%文字を持っている場合、驚くべき結果が得られる可能性があります。2つのステップを使用する方が安全です。
#! /usr/bin/env perl
use strict;
use warnings;
my @float_values = (1.0e5, 3.14159, 2.71828);
for my $f (@float_values) {
my $arg5 = sprintf "%e", $f;
system(qq[./fermions $arg5 "string" >> outfile.out]) == 0
or warn "$0: fermions failed";
}
構文に慣れていない場合はqq[...]
、二重引用符で囲まれた文字列のように機能しますが、区切り文字が異なるため、コマンドで二重引用符をエスケープする必要はありません。
活字の目的で他の引数を省略したことに注意してください。ただし、の値とともにそれらを補間することができます$arg5
。もう1つの微妙な変更は、クラバリング>>
ではなく追加用に切り替えることです。>
の代役を使用するfermions
#! /usr/bin/env perl
$" = "][";
warn "[@ARGV]\n";
一緒に実行されている2つのプログラムの出力は
[1.000000e +05][文字列]
[3.141590e +00][文字列]
[2.718280e +00][文字列]
用語に関して、システムコールとは、オペレーティングシステムからのサービスに対する低レベルの要求を指します。たとえば、、、、open
などclose
ですunlink
。Perlのシステム関数はシステムコールを利用しますが、2つの概念は異なります。
シェルがコマンドライン引数を混乱させないようにするために、perlipcの「SafePipeOpens」セクションで説明されている手法を使用してください。Perlsystem
とexec
関数は、コマンド全体を含む単一の文字列ではなく、引数のリストが与えられるとシェルをバイパスします。
標準出力をリダイレクトしたいので、状況は少しトリッキーです。以下のコードは、子をフォークし、子STDOUT
をに追加するように設定してから、子でoutfile.out
実行fermion
しexec
ます。親は子が終了するのを待ち、失敗を報告します。
#! /usr/bin/env perl
use strict;
use warnings;
my @float_values = (1.0e5, 3.14159, 2.71828);
for my $f (@float_values) {
my $arg5 = sprintf "%e", $f;
my $pid = fork;
if (defined $pid) {
if ($pid == 0) {
my $path = "outfile.out";
open STDOUT, ">>", $path or die "$0: open $path: $!";
exec "./fermions", $arg5, "string" or die "$0: exec: $!";
}
else {
local $!;
my $pid = waitpid $pid, 0;
warn "$0: waitpid: $!" if $pid == -1 && $!;
warn "$0: fermion exited " . ($? >> 8) if $?;
}
}
else {
die "$0: fork: $!";
}
}