2012-04-21 4 views
2

私のPerlプログラムから、systemを使ってCで書かれた別のコマンドを実行しようとしています。このコマンドには、文字列、浮動小数点数、2つの整数、浮動小数点数の組、および別の文字列が必要です。私はいくつかの異なる浮動小数点値であることが$arg5を変更する必要がPerlのsystem()形式の引数を科学的表記法で作成するにはどうすればよいですか?

my $arg1="electron"; 
my $arg2=0.511; 
# more definitions 
system("./fermions $arg1 $arg2 $arg3 $arg4 " . 
     "$arg5 $arg6 \"string\" > outfile.out"); 

としてこれを実行しています。私は$arg5="1.0e5"を設定し、forループでifステートメントを実行して値を文字列として変更して動作させました。私は浮動小数点としてこれを行うことができるようにしたいと思ったし、試した

system("./fermions $arg1 $arg2 $arg3 $arg4 " . 
     "%e $arg6 \"string\" >outfile.out", 
     $arg5); 

しかし、それは動作しませんでした。別の選択肢がありますか、またはif文オプションが唯一のものですか?

+0

「システムリスト」または「システム{プログラム名}リスト[呼び出し]」(http://perldoc.perl.org/functions/system.html)をご検討ください。いつか、多くのリファクタ、 '$ arg2'が' 'rm -rf /' 'になると、もっと安全になります。シェル出力のリダイレクトを使用することはできませんが、 'outfile.out'を自分で開き、STDOUTにdupするか、シェルスクリプト内の'。/ fermions'をラップして出力をキャプチャすることができます。 – pilcrow

+0

。私はこれについて私のコードを修正するが、私は、この時点で、将来の使用のためにこの質問をしている。 –

答えて

6

"%e"のようなprintf表記を使用する場合は、Perl sprintf組み込み関数を使用する必要があります。それ以外の場合は、リテラル引数として "%e"を渡すだけです。

1

重要:あなたが常には、コマンドが失敗したかどうかを判断するために、Perlのsystem関数からの戻り値をチェックする必要があります。

float値のフォーマットには、次のコードのようにPerlのsprintfを使用します。はい、フォーマット指定子としてコマンドを使用することで逃げることができますが、コマンドの%文字が他の場所にあると驚くべき結果になる可能性があります。 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と一緒に補間できます。もう一つの微妙な変更は、>ではなく、追加するための>>への切り替えです。

fermions

#! /usr/bin/env perl 
$" = "]["; 
warn "[@ARGV]\n"; 

のために一緒に実行している2つのプログラムの出力をスタンドインを使用して用語に関して

[1.000000e+05][string] 
[3.141590e+00][string] 
[2.718280e+00][string]

で、システムコールのための低レベルの要求を指しオペレーティングシステムからのサービス,open,close,unlinkなどが挙げられる。 Perlのシステム関数はシステムコールを使用しますが、2つの概念は区別されます。

実際にはであることを確認してください。シェルがコマンドライン引数を無視しないようにするには、“Safe Pipe Opens” section of perlipcに記載されている方法を使用してください。 Perlのsystemexec関数は、コマンド全体を含む単一の文字列ではなく、引数のリストが与えられたときにシェルをバイパスします。

標準出力をリダイレクトしたいので状況が少し複雑です。以下のコードは子をフォークし、子のSTDOUToutfile.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: $!"; 
    } 
} 
関連する問題