16

Perl と PHP はこれをバッククォートで行います。例えば、

$output = `ls`;

ディレクトリ リストを返します。同様の関数 はsystem("foo")、指定されたコマンド foo のオペレーティング システムのリターン コードを返します。私は、foo が出力するものを標準出力に返すバリアントについて話している。

他の言語はどのようにこれを行いますか? この関数の正規名はありますか? (私は "backtick" を使用します。ただし、"syslurp" という造語を使用することもできます。)

4

27 に答える 27

20

パイソン

from subprocess import check_output as qx

output = qx(['ls', '-lt'])

Python < 2.7または < 3.1

subprocess.pysubprocess.check_output()から抽出するか、次のようなものを適用します。

import subprocess

def cmd_output(args, **kwds):
  kwds.setdefault("stdout", subprocess.PIPE)
  kwds.setdefault("stderr", subprocess.STDOUT)
  p = subprocess.Popen(args, **kwds)
  return p.communicate()[0]

print cmd_output("ls -lt".split())

subprocessモジュールは2.4 以降、stdlib に含まれています。

于 2008-10-25T19:35:50.810 に答える
12

パイソン:

import os
output = os.popen("foo").read()
于 2008-10-25T17:53:24.917 に答える
9

[ Alexmandreevesの要請により-- コメントを参照してください --、このDZones Java Snippet ページで、この例では 'ls' を作成するための完全なバージョンの OS 非依存を見つけることができます。これは彼らのcode-challengeに対する直接的な答えです。
以下は単なるコアです: Runtime.exec に加えて、stdout と stderr をリッスンする 2 つのスレッド。]

Java "簡単!":

E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Executing cmd.exe /C dir *.java
...

またはJavaコードで

String output = GoodWindowsExec.execute("dir");

しかし、そのためにはコーディングが必要です...
...これは恥ずかしいです。

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
    InputStream is;
    String type;
    StringBuffer output = new StringBuffer();

    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }

    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);
                output.append(line+"\r\n")
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
    public String getOutput()
    {
        return this.output.toString();
    }
}
public class GoodWindowsExec
{
    public static void main(String args[])
    {
        if (args.length < 1)
        {
            System.out.println("USAGE: java GoodWindowsExec <cmd>");
            System.exit(1);
        }
    }
    public static String execute(String aCommand)
    {
        String output = "";
        try
        {            
            String osName = System.getProperty("os.name" );
            String[] cmd = new String[3];
            if( osName.equals( "Windows 95" ) )
            {
                cmd[0] = "command.com" ;
                cmd[1] = "/C" ;
                cmd[2] = aCommand;
            }
            else if( osName.startsWith( "Windows" ) )
            {
                cmd[0] = "cmd.exe" ;
                cmd[1] = "/C" ;
                cmd[2] = aCommand;
            }

            Runtime rt = Runtime.getRuntime();
            System.out.println("Executing " + cmd[0] + " " + cmd[1] 
                               + " " + cmd[2]);
            Process proc = rt.exec(cmd);
            // any error message?
            StreamGobbler errorGobbler = new 
                StreamGobbler(proc.getErrorStream(), "ERROR");            

            // any output?
            StreamGobbler outputGobbler = new 
                StreamGobbler(proc.getInputStream(), "OUTPUT");

            // kick them off
            errorGobbler.start();
            outputGobbler.start();

            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);   

            output = outputGobbler.getOutput();
            System.out.println("Final output: " + output);   

        } catch (Throwable t)
          {
            t.printStackTrace();
          }
        return output;
    }
}
于 2008-10-25T19:19:25.057 に答える
8

Perl でそれを行うさらに別の方法 (TIMTOWTDI)

$output = <<`END`;
ls
END

これは、比較的大きなシェル スクリプトを Perl プログラムに埋め込む場合に特に便利です。

于 2008-10-25T18:12:30.153 に答える
7

ハスケル:

import Control.Exception
import System.IO
import System.Process
main = bracket (runInteractiveCommand "ls") close $ \(_, hOut, _, _) -> do
    output <- hGetContents hOut
    putStr output
  where close (hIn, hOut, hErr, pid) =
          mapM_ hClose [hIn, hOut, hErr] >> waitForProcess pid

MissingHがインストールされている場合:

import System.Cmd.Utils
main = do
    (pid, output) <- pipeFrom "ls" []
    putStr output
    forceSuccess pid

これは、Perl や Ruby などの「接着」言語では簡単な操作ですが、Haskell ではそうではありません。

于 2008-10-27T21:43:51.940 に答える
7

Ruby: バッククォートまたは '%x' 組み込み構文のいずれか。

puts `ls`;
puts %x{ls};
于 2008-10-25T18:02:29.237 に答える
7

perl の代替方法

$output = qx/ls/;

これには、区切り文字を選択できるという利点があり、コマンドで ` を使用できるようになりました (ただし、本当に必要な場合は設計を再検討する必要があります)。別の重要な利点は、単一引用符を区切り文字として使用すると、変数が補間されないことです (非常に便利です)。

于 2008-10-25T18:08:02.860 に答える
6

これはシステムに依存するため、必要なさまざまなシステムコール用の組み込みラッパーがない言語がたくさんあります。

たとえば、CommonLisp自体は特定のシステムで実行するようには設計されていません。ただし、SBCL(Steel Banks Common Lisp実装)は、他のほとんどのCL実装と同様に、Unixライクなシステムの拡張機能を提供します。もちろん、これは単に出力を取得するよりもはるかに「強力」です(実行中のプロセスを制御でき、あらゆる種類のストリーム方向を指定できます。SBCLマニュアルの6.3章を参照してください)が、簡単に実行できます。この特定の目的のために小さなマクロを書いてください:

(defmacro with-input-from-command((stream-name command args)&body body)
  "コマンドの出力ストリームをstream-nameにバインドしてから、本文を実行します
   暗黙の予測で。」
  `(with-open-stream
       (、ストリーム名
         (sb-ext:process-output(sb-ext:run-program、command
                                                    、args
                                                    :検索t
                                                    :output:stream)))
     、@体))

これで、次のように使用できます。

(with-input-from-command(ls "ls"'( "-l"))
  ;;lsストリームで派手なことをする
  )。

おそらく、すべてを1つの文字列にまとめたいと思うでしょう。マクロは簡単です(おそらくもっと簡潔なコードが可能ですが):

(defmacro syslurp(コマンド引数)
  "コマンドからの出力を文字列として返します。コマンドが提供されます
   文字列として、文字列のリストとしてargs。」
  (let((istream(gensym))
        (ostream(gensym))
        (line(gensym)))
    `(with-input-from-command(、istream、command、args)
       (with-output-to-string(、ostream)
         (loop(let((、line(read-line、istream nil)))
                 (when(null、line)(return))
                 (write-line、line、ostream))))))))

これで、次の呼び出しで文字列を取得できます。

(syslurp "ls"'( "-l"))
于 2008-12-12T23:12:26.497 に答える
6

シェル内

OUTPUT=`ls`

または代わりに

OUTPUT=$(ls)

この 2 番目の方法は、ネストできるため優れていますが、最初の方法とは異なり、すべてのシェルでサポートされているわけではありません。

于 2008-10-25T18:00:43.327 に答える
6

アーラン:

os:cmd("ls")
于 2008-10-25T18:10:11.170 に答える
4

C#3.0、これよりも冗長ではありません:

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        var info = new ProcessStartInfo("cmd", "/c dir") { UseShellExecute = false, RedirectStandardOutput = true };
        Console.WriteLine(Process.Start(info).StandardOutput.ReadToEnd());
    }
}

警告:本番コードはProcessオブジェクトを適切に破棄する必要があります...

于 2009-01-11T12:37:39.573 に答える
4

Tcl を忘れないでください:

set result [exec ls]
于 2008-12-02T19:57:15.160 に答える
4

何年も前に、ネイティブ アプリケーションに接続するjEdit用のプラグインを作成しました。これは、実行中の実行可能ファイルからストリームを取得するために使用したものです。やるべきことは次のとおりです。while((String s = stdout.readLine())!=null){...}

/* File:    IOControl.java
 *
 * created: 10 July 2003
 * author:  dsm
 */
package org.jpop.io;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;

/**
 *  Controls the I/O for a process. When using the std[in|out|err] streams, they must all be put on
 *  different threads to avoid blocking!
 *
 * @author     dsm
 * @version    1.5
 */
public class IOControl extends Object {
    private Process process;
    private BufferedReader stdout;
    private BufferedReader stderr;
    private PrintStream stdin;

    /**
     *  Constructor for the IOControl object
     *
     * @param  process  The process to control I/O for
     */
    public IOControl(Process process) {
        this.process = process;
        this.stdin = new PrintStream(process.getOutputStream());
        this.stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
        this.stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    }

    /**
     *  Gets the stdin attribute of the IOControl object
     *
     * @return    The stdin value
     */
    public PrintStream getStdin() {
        return this.stdin;
    }

    /**
     *  Gets the stdout attribute of the IOControl object
     *
     * @return    The stdout value
     */
    public BufferedReader getStdout() {
        return this.stdout;
    }

    /**
     *  Gets the stderr attribute of the IOControl object
     *
     * @return    The stderr value
     */
    public BufferedReader getStderr() {
        return this.stderr;
    }

    /**
     *  Gets the process attribute of the IOControl object. To monitor the process (as opposed to
     *  just letting it run by itself) its necessary to create a thread like this: <pre>
     *. IOControl ioc;
     *.
     *. new Thread(){
     *.     public void run(){
     *.         while(true){    // only necessary if you want the process to respawn
     *.             try{
     *.                 ioc = new IOControl(Runtime.getRuntime().exec("procname"));
     *.                 // add some code to handle the IO streams
     *.                 ioc.getProcess().waitFor();
     *.             }catch(InterruptedException ie){
     *.                 // deal with exception
     *.             }catch(IOException ioe){
     *.                 // deal with exception
     *.             }
     *.
     *.             // a break condition can be included here to terminate the loop
     *.         }               // only necessary if you want the process to respawn
     *.     }
     *. }.start();
     *  </pre>
     *
     * @return    The process value
     */
    public Process getProcess() {
        return this.process;
    }
}
于 2008-10-30T21:10:11.773 に答える
4

Perl でのさらに別の方法 (または 2!)...

open my $pipe, 'ps |';
my @output = < $pipe >;
say @output;

openは次のように書くこともできます...

open my $pipe, '-|', 'ps'
于 2008-10-25T20:57:18.587 に答える
4

マテマティカ:

output = Import["!foo", "Text"];
于 2008-10-25T17:46:09.097 に答える
3

これが別のLispの方法です:

(defun execute (program parameters &optional (buffer-size 1000))
  (let ((proc (sb-ext:run-program program parameters :search t :output :stream))
        (output (make-array buffer-size :adjustable t :fill-pointer t 
                            :element-type 'character)))
    (with-open-stream (stream (sb-ext:process-output proc))
      (setf (fill-pointer output) (read-sequence output stream)))
    output))

次に、文字列を取得するには:

(execute "cat" '("/etc/hosts"))

大量の情報をSTDOUTに出力するコマンドを実行する場合は、次のように実行できます。

(execute "big-writer" '("some" "parameters") 1000000)

最後のパラメーターは、ビッグライターからの出力用に大量のスペースを事前に割り当てます。この関数は、一度に1行ずつ出力ストリームを読み取るよりも高速である可能性があると思います。

于 2009-09-03T07:36:54.480 に答える
3

Posix準拠システムのCの場合:

#include <stdio.h> 

FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);
于 2008-12-16T22:59:24.833 に答える
3

ここにまだ c# 担当者がいないのはなぜですか :)

これは、C# で行う方法です。組み込みの方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.FileName = "cmd";
            p.StartInfo.Arguments = "/c dir";
            p.Start();

            string res = p.StandardOutput.ReadToEnd();
            Console.WriteLine(res);
        }

    }
}
于 2008-12-23T04:26:56.193 に答える
3

ルア

    foo = io.popen("ls"):read("*a")
于 2009-09-03T07:48:54.467 に答える
3

パール:

$output = `foo`;

追加: これは本当に多面的な結びつきです. 上記はPHPでも有効で、例えばRubyでも同じバッククォート表記が使われています。

于 2008-10-25T17:45:31.250 に答える
3

C (glibc拡張子あり):

#define _GNU_SOURCE
#include <stdio.h>
int main() {
    char *s = NULL;
    FILE *p = popen("ls", "r");
    getdelim(&s, NULL, '\0', p);
    pclose(p);
    printf("%s", s);
    return 0;
}

わかりました、本当に簡潔でもきれいでもありません。それがCでの生活です...

于 2008-10-27T21:19:53.080 に答える
3

PHPで

$output = `ls`;

また

$output = shell_exec('ls');
于 2008-10-25T18:03:59.873 に答える
2

Perl、別の方法:

use IPC::Run3

my ($stdout, $stderr);
run3 ['ls'], undef, \$stdout, \$stderr
    or die "ls failed";

コマンド入力をフィードし、stderrとstdoutの両方を別々に戻すことができるので便利です。IPC::Runサブルーチンへのパイプを設定できる、きちんとした/怖い/遅い/邪魔なものはどこにもありません。

于 2008-12-16T19:39:36.030 に答える
2

アイコン/ユニコン:

stream := open("ls", "p")
while line := read(stream) do { 
    # stuff
}

ドキュメントではこれをパイプと呼んでいます。良い点の 1 つは、出力がファイルを読み取っているように見えることです。また、必要に応じて、アプリの stdin に書き込むことができることも意味します。

于 2008-12-23T05:07:00.637 に答える
2

Clozure Common Lisp:

(with-output-to-string (stream)
   (run-program "ls" '("-l") :output stream))

LispWorks

(with-output-to-string (*standard-output*)
  (sys:call-system-showing-output "ls -l" :prefix "" :show-cmd nil))
于 2009-09-03T10:07:12.637 に答える
2

J :

output=:2!:0'ls'
于 2008-10-27T21:21:56.697 に答える