Frage

Perl und PHP tun dies mit Backticks. Zum Beispiel:

$output = `ls`;

Gibt eine Verzeichnisliste. Eine ähnliche Funktion, system("foo"), kehrt der Betriebssystem-Rückkehrcode für den gegebenen Befehl foo. Ich spreche von einer Variante, die unabhängig von foo druckt auf stdout zurück.

Wie andere Sprachen tun? Gibt es einen kanonischen Namen für diese Funktion? (Ich werde mit „Graviszeichen.“; Aber vielleicht könnte ich Münze „syslurp“)

War es hilfreich?

Lösung 20

Perl:

$output = `foo`;

ADDED: Das ist wirklich eine Mehrweg-Bindung. Die obige gilt auch PHP und Ruby zum Beispiel verwendet die gleiche Graviszeichen Notation als auch.

Andere Tipps

Python

from subprocess import check_output as qx

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

Python << a href = "http://docs.python.org/dev/library/subprocess.html#subprocess.check_output" rel = "noreferrer"> 2.7 oder << a href =“ http://docs.python.org/py3k/library/subprocess.html#subprocess.check_output“rel = "noreferrer"> 3.1

Extract subprocess.check_output() von subprocess.py oder anpassen etwas ähnliches wie:

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())

Die subprocess Modul ist seit 2.4 im stdlib gewesen.

Python:

import os
output = os.popen("foo").read()

[Auf Antrag der Alexman und dreeves - siehe Kommentare -, werden Sie in diesem Code-Herausforderung .
Was unten folgt, ist nur der Kern: Runtime.exec, plus 2 Gewinde auf stdout und stderr zu hören. ]

Java "Simple":

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

oder in Java-Code

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

Aber das zu tun, müssen Sie Code ...
... das ist peinlich.

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;
    }
}

Eine weitere Möglichkeit, es in Perl (TIMTOWTDI) zu tun

$output = <<`END`;
ls
END

Dies ist besonders nützlich, wenn ein relativ großes Shell-Skript in einem Perl-Programm einbetten

Rubin: entweder Backticks oder die '% x' builtin Syntax

.
puts `ls`;
puts %x{ls};

Eine alternative Methode in Perl

$output = qx/ls/;

Dies hatte den Vorteil, dass Sie Ihre Trennzeichen wählen können, was es möglich macht `in dem Befehl verwendet werden (obwohl IMHO sollten Sie Ihr Design überdenken, wenn Sie wirklich, dass müssen tun). Ein weiterer wichtiger Vorteil ist, dass, wenn Sie einfache Anführungszeichen als Trennzeichen verwenden, Variablen nicht (sehr nützlich) interpoliert werden

Haskell:

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

Mit missingh installiert:

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

Dies ist eine einfache Bedienung in "Klebstoff" Sprachen wie Perl und Ruby, aber Haskell ist es nicht.

In Shell

OUTPUT=`ls`

oder alternativ

OUTPUT=$(ls)

Diese zweite Methode ist besser, weil es Verschachtelung erlaubt, werden aber nicht von allen Shells unterstützt, im Gegensatz zu dem ersten Verfahren.

Erlang:

os:cmd("ls")

Nun, da dieses System abhängig ist, gibt es viele Sprachen, die notwendig für die verschiedenen Systemaufrufe nicht über einen eingebauten in Wrapper haben.

Zum Beispiel Common Lisp selbst wurde nicht auf einem bestimmten System laufen konzipiert. SBCL (der Stahl Banks Common Lisp-Implementierung), hat aber für eine Erweiterung bieten Unix-ähnlichen Systemen, wie die meisten anderen CL-Implementierungen tun. Das ist viel mehr „mächtig“, als nur den Ausgang bekommen, natürlich (Sie die Kontrolle über den laufenden Prozess haben, alle Arten von Strom Richtungen angeben usw. verleihen zum SBCL Handbuch, Kapitel 6.3), aber es ist leicht zu schreibt ein wenig Makro für diesen speziellen Zweck:

(defmacro with-input-from-command ((stream-name command args) &body body)
  "Binds the output stream of command to stream-name, then executes the body
   in an implicit progn."
  `(with-open-stream
       (,stream-name
         (sb-ext:process-output (sb-ext:run-program ,command
                                                    ,args
                                                    :search t
                                                    :output :stream)))
     ,@body))

Jetzt können Sie es wie folgt verwendet werden:

(with-input-from-command (ls "ls" '("-l"))
  ;;do fancy stuff with the ls stream
  )

Vielleicht möchten Sie es alle in eine Zeichenfolge schlürfen. Das Makro ist trivial (wenn auch vielleicht prägnanter Code ist möglich):

(defmacro syslurp (command args)
  "Returns the output from command as a string. command is to be supplied
   as string, args as a list of strings."
  (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)))))))

Jetzt können Sie einen String mit diesem Anruf erhalten:

(syslurp "ls" '("-l"))

Mathematica:

output = Import["!foo", "Text"];

Vor Jahren schrieb ich ein Plugin jEdit , die eine native Anwendung angeschlossen. Dies ist, was ich verwenden, um die Ströme von dem Laufe ausführbaren Datei zu erhalten. Nur, was ist while((String s = stdout.readLine())!=null){...} mehr zu tun:

/* 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;
    }
}

Sie nicht Tcl vergessen:

set result [exec ls]

C # 3.0, weniger ausführlich als dieses :

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());
    }
}

Caveat: Produktionscode sollte das Prozessobjekt entsorgen ...

Noch eine andere Art und Weise (oder 2!) In Perl ....

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

öffnen kann auch wie so geschrieben werden ...

open my $pipe, '-|', 'ps'

In PHP

$output = `ls`;

oder

$output = shell_exec('ls');

C (mit glibc Erweiterung):

#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;
}

Okay, nicht wirklich prägnante oder sauber. So ist das Leben in C ...

C auf Posix-konformen Systemen:

#include <stdio.h> 

FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);

Warum gibt es noch keinen c # Kerl hier:)

Dies ist, wie es in C # zu tun. Die integrierte Möglichkeit.

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);
        }

    }
}

Hier ist eine andere Art und Weise 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))

Dann, um Ihren string:

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

Wenn Sie einen Befehl ausführen möchten, die ein hohes Maß an Informationen zu STDOUT schafft druckt, können Sie es wie folgt aus:

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

Der letzte Parameter zuweist eine große Menge an Platz für die Ausgabe von großen Schriftstellern. Ich vermute, diese Funktion schneller sein könnte, den Ausgangsstrom eine Zeile zu einem Zeitpunkt, als das Lesen.

Lua :

    foo = io.popen("ls"):read("*a")

J :

output=:2!:0'ls'

Perl, eine andere Art und Weise:

use IPC::Run3

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

Nützliche, weil Sie die Befehlseingabe einspeisen kann und separat sowohl stderr und stdout zurück. Bei weitem nicht so ordentlich / beängstigend / langsam / störend als IPC::Run, die Rohre zu Subroutinen einrichten.

Icon / Unicon:

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

Die docs nennen dies eine Pfeife. Eines der guten Dinge ist, dass er den Ausgang Look macht wie Sie nur eine Datei zu lesen. Es bedeutet auch, können Sie auf der App-stdin schreiben, wenn Sie müssen.

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))

Zugegeben, es ist nicht die kleiner (von allen Sprachen verfügbar), aber es sollte nicht so umfangreich sein.

Diese Version ist verschmutzt. Ausnahmen behandelt werden soll, Lesen verbessert werden. Dies ist nur zu zeigen, wie eine Java-Version starten könnte.

Process p = Runtime.getRuntime().exec( "cmd /c " + command );
InputStream i = p.getInputStream();
StringBuilder sb = new StringBuilder();
for(  int c = 0 ; ( c =  i.read() ) > -1  ; ) {
    sb.append( ( char ) c );
}

Das Gesamtprogramm unten.

import java.io.*;

public class Test { 
    public static void main ( String [] args ) throws IOException { 
        String result = execute( args[0] );
        System.out.println( result );
    }
    private static String execute( String command ) throws IOException  { 
        Process p = Runtime.getRuntime().exec( "cmd /c " + command );
        InputStream i = p.getInputStream();
        StringBuilder sb = new StringBuilder();
        for(  int c = 0 ; ( c =  i.read() ) > -1  ; ) {
            sb.append( ( char ) c );
        }
        i.close();
        return sb.toString();
    }
}

Beispiel ouput (mit dem Befehl type)

C:\oreyes\samples\java\readinput>java Test "type hello.txt"
This is a sample file
with some
lines

Eine Beispielausgabe (dir)

 C:\oreyes\samples\java\readinput>java Test "dir"
 El volumen de la unidad C no tiene etiqueta.
 El número de serie del volumen es:

 Directorio de C:\oreyes\samples\java\readinput

12/16/2008  05:51 PM    <DIR>          .
12/16/2008  05:51 PM    <DIR>          ..
12/16/2008  05:50 PM                42 hello.txt
12/16/2008  05:38 PM             1,209 Test.class
12/16/2008  05:47 PM               682 Test.java
               3 archivos          1,933 bytes
               2 dirs            840 bytes libres

Versuchen Sie jede

java Test netstat
java Test tasklist
java Test "taskkill /pid 416"

Bearbeiten

Ich muss zugeben, dass ich nicht 100% sicher bin, das die „beste“ Weg, es zu tun. Fühlen Sie sich frei zu veröffentlichen Referenzen und / oder Code zu zeigen, wie kann es verbessert werden oder was ist los mit diesem.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top