2

在我的 Perl 程序中,我试图运行另一个用 C 编写的命令,使用system. 该命令需要几个参数:一个字符串、一个浮点数、两个整数、一对浮点数和另一个字符串。我正在运行这个

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

我需要改变$arg5为几个不同的浮点值。我通过设置$arg5="1.0e5"然后在 for 循环中运行 if 语句以将值更改为字符串来使其工作。我希望能够以浮动方式执行此操作,并尝试过

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

但这没有用。还有另一种选择,还是我的 if 语句选项是唯一的?

4

2 回答 2

6

如果你想使用 printf 表示法(比如“%e”),你需要使用 Perl 的sprintf内建函数。否则,您最终只会将“%e”作为文字参数传递。

于 2012-04-21T02:35:27.503 回答
1

重要提示:您应该始终检查 Perlsystem函数的返回值以确定命令是否失败。

使用 Perlsprintf来格式化浮点值,如下面的代码所示。是的,您可以不使用该命令作为格式说明符,但如果该命令在其他地方有杂散的 % 字符,您可能会得到令人惊讶的结果。使用两个步骤更安全。

#! /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";

两个程序一起运行的输出是

[1.000000e+05][字符串]
[3.141590e+00][字符串]
[2.718280e+00][字符串]

就术语而言,系统调用是指来自操作系统的低级服务请求,例如opencloseunlink等等。尽管 Perl 的系统函数使用系统调用,但这两个概念是不同的。

为了确保 shell不会伪造你的命令行参数,请使用perlipc 的“安全管道打开”部分中描述的技术。当给定参数列表而不是包含整个命令的单个字符串时,Perlsystem和函数会绕过 shell。exec

您的情况有点棘手,因为您想重定向标准输出。下面的代码 fork 一个孩子,将孩子设置STDOUT为 append outfile.out,然后在孩子中运行fermionwith 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: $!";
  }
}
于 2012-04-21T13:13:05.617 回答