【问题标题】:How do I store the value returned by either run or shell?如何存储 run 或 shell 返回的值?
【发布时间】:2018-12-31 04:32:35
【问题描述】:

假设我有这个脚本:

# prog.p6
my $info = run "uname";

当我运行prog.p6 时,我得到:

$ perl6 prog.p6
Linux

有没有办法存储返回值的字符串化版本并防止它被输出到终端?

已经有一个similar question,但它没有提供具体的答案。

【问题讨论】:

标签: raku


【解决方案1】:

您需要通过设置:out 来启用默认为$*OUT 的标准输出管道。所以:

my $proc = run("uname", :out);
my $stdout = $proc.out;
say $stdout.slurp;
$stdout.close;

可以简写为:

my $proc = run("uname", :out);
say $proc.out.slurp(:close);

如果您想在 stderr 上与 stdout 分开捕获输出,您可以这样做:

my $proc = run("uname", :out, :err);
say "[stdout] " ~ $proc.out.slurp(:close);
say "[stderr] " ~ $proc.err.slurp(:close);

或者如果您想将 stdout 和 stderr 捕获到一个管道,那么:

my $proc = run("uname", :merge);
say "[stdout and stderr] " ~ $proc.out.slurp(:close);

最后,如果你不想捕获输出也不希望它输出到终端:

my $proc = run("uname", :!out, :!err);
exit( $proc.exitcode );

【讨论】:

    【解决方案2】:

    此答案中涵盖的解决方案很简洁。

    这有时胜过它的缺点:

    • 不存储结果代码。如果需要,请改用 ugexe 的解决方案。

    • 不将输出存储到标准错误。如果需要,请改用 ugexe 的解决方案。

    • 潜在的漏洞。这在下面解释。请考虑使用 ugexe 的解决方案。


    下面解释的功能文档以the quote adverb :exec开头。

    最安全的不安全变体:q

    最安全的变体使用单个q

    say qx[ echo 42 ] # 42
    

    如果有错误,则构造返回一个空字符串,任何错误消息都会出现在 stderr 上。

    这种最安全的变体类似于传递给 shell 的 引用字符串,如 'foo'。单引号字符串没有interpolate,因此code injection attack 没有漏洞。

    也就是说,您将单个字符串传递给 shell,它可能不是您期望的 shell,因此它可能无法按您的期望解析字符串。

    最不安全的不安全变体:qq

    以下行产生与q 行相同的结果,但使用了最不安全的变体:

    say qqx[ echo 42 ]
    

    这个双 q 变体类似于双引号字符串 ("foo")。这种形式的字符串引用 确实 进行插值,这意味着如果您在传递给 shell 的字符串中包含变量,它会受到 code injection attack 的影响。

    【讨论】:

      【解决方案3】:

      默认情况下run 只是将STDOUTSTDERR 传递给父进程的STDOUTSTDERR

      你必须告诉它做其他事情。

      最简单的方法是给它:out 告诉它保留STDOUT。 (:out(True)的缩写)

      my $proc = run 'uname', :out;
      my $result = $proc.out.slurp(:close);
      
      my $proc = run 'uname', :out;
      for $proc.out.lines(:close) {
        .say;
      }
      

      您也可以有效地告诉它只需将STDOUT 发送到/dev/null:!out。 (:out(False)的缩写)


      您可以使用:out 做更多的事情

      {
        my $file will leave {.close} = open :w, 'test.out';
        run 'uname', :out($file); # write directly to a file
      }
      
      print slurp 'test.out'; # Linux
      
      my $proc = run 'uname', :out;
      
      react {
        whenever $proc.out.Supply {
          .print
      
          LAST {
            $proc.out.close;
            done; # in case there are other whenevers
          }
        }
      }
      

      如果您要执行最后一个,最好使用 Proc::Async。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-09
        • 2017-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        • 2010-12-12
        相关资源
        最近更新 更多