Domanda

Perl e PHP lo fanno con i backtick. Ad esempio,

$output = `ls`;

Restituisce un elenco di directory. Una funzione simile, system("foo"), restituisce il codice di ritorno del sistema operativo per il comando foo specificato. Sto parlando di una variante che restituisce a stdout qualunque stampa foo.

Come lo fanno le altre lingue? Esiste un nome canonico per questa funzione? (Vado con & Quot; backtick & Quot ;; anche se forse potrei coniare & Quot; syslurp & Quot ;.)

È stato utile?

Soluzione 20

Perl:

$output = `foo`;

AGGIUNTO: è davvero un pareggio a più vie. Quanto sopra è anche valido PHP e Ruby, ad esempio, usa anche la stessa notazione backtick.

Altri suggerimenti

Python

from subprocess import check_output as qx

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

Python < 2.7 o lt; 3.1

Estrai subprocess.check_output() da subprocess.py o adattare qualcosa di simile a:

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

Il modulo sottoprocesso è in fase di stdlib dal 2.4.

Python:

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

[Su richiesta di Alexman e dreeves - vedi commenti -, troverai in questo Pagina dello snippet Java di DZones una versione completa indipendente da Os per rendere, in questo caso, un 'ls'. Questa è una risposta diretta al loro codice-sfida .
Quello che segue è solo il core: Runtime.exec, più 2 thread per ascoltare stdout e stderr. ]

Java " Semplice! " ;:

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

O nel codice Java

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

Ma per farlo, devi codificare ...
... Questo è imbarazzante.

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

Ancora un altro modo per farlo in Perl (TIMTOWTDI)

$output = <<`END`;
ls
END

Ciò è particolarmente utile quando si incorpora uno script shell relativamente grande in un programma Perl

Ruby: backtick o sintassi incorporata '% x'.

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

Un metodo alternativo in perl

$output = qx/ls/;

Ciò ha avuto il vantaggio di poter scegliere i delimitatori, rendendo possibile l'uso di `nel comando (anche se IMHO dovresti riconsiderare il tuo progetto se davvero hai bisogno di farlo). Un altro vantaggio importante è che se si utilizzano virgolette singole come delimitatore, le variabili non verranno interpolate (molto utili)

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

Con MissingH installato:

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

Questa è un'operazione facile in " colla " lingue come Perl e Ruby, ma Haskell no.

In shell

OUTPUT=`ls`

o in alternativa

OUTPUT=$(ls)

Questo secondo metodo è migliore perché consente l'annidamento, ma non è supportato da tutte le shell, a differenza del primo metodo.

Erlang:

os:cmd("ls")

Bene, poiché questo dipende dal sistema, ci sono molte lingue che non hanno un wrapper integrato per le varie chiamate di sistema necessarie.

Ad esempio, Common Lisp stesso non è stato progettato per funzionare su alcun sistema specifico. SBCL (l'implementazione di Steel Banks Common Lisp), tuttavia, fornisce un'estensione per sistemi simili a Unix, così come la maggior parte delle altre implementazioni CL. Questo è molto più & Quot; potente & Quot; oltre a ottenere l'output, ovviamente (hai il controllo del processo in esecuzione, puoi specificare tutti i tipi di direzioni del flusso, ecc., conferire al manuale SBCL, capitolo 6.3), ma è facile scrivere una piccola macro per questo specifico scopo:

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

Ora puoi usarlo in questo modo:

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

Forse vuoi assimilare tutto in una stringa. La macro è banale (anche se forse è possibile un codice più conciso):

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

Ora puoi ottenere una stringa con questa chiamata:

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

Mathematica:

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

Anni fa ho scritto un plugin per jEdit che si è interfacciato con un'applicazione nativa. Questo è quello che ho usato per ottenere i flussi dall'eseguibile in esecuzione. L'unica cosa che resta da fare è 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;
    }
}

Non dimenticare Tcl:

set result [exec ls]

C # 3.0, meno dettagliato di questo :

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

Avvertenza: il codice di produzione deve disporre correttamente dell'oggetto Process ...

Ancora un altro modo (o 2!) in Perl ....

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

open può anche essere scritto in questo modo ...

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

In PHP

$output = `ls`;

o

$output = shell_exec('ls');

C (con glibc estensione):

#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, non molto conciso o pulito. Questa è la vita in C ...

In C su sistemi conformi Posix:

#include <stdio.h> 

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

Perché non c'è ancora nessun ragazzo c # qui :)

Ecco come farlo in C #. Il modo integrato.

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

    }
}

Ecco un altro modo 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))

Quindi, per ottenere la tua stringa:

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

Se vuoi eseguire un comando che crea stampe una grande quantità di informazioni su STDOUT, puoi eseguirlo in questo modo:

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

L'ultimo parametro prealloca una grande quantità di spazio per l'output di big-writer. Immagino che questa funzione potrebbe essere più veloce della lettura del flusso di output una riga alla volta.

Lua :

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

J :

output=:2!:0'ls'

Perl, un altro modo:

use IPC::Run3

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

Utile perché è possibile alimentare l'input del comando e recuperare separatamente sia stderr che stdout. In nessun luogo vicino come pulito / spaventoso / lento / inquietante come IPC::Run, che può impostare pipe per subroutine.

Icona / Unicon:

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

I documenti lo chiamano pipe. Una delle cose buone è che fa sembrare che l'output stia solo leggendo un file. Significa anche che puoi scrivere sullo stdin dell'app, se necessario.

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

Certo, non è il più piccolo (tra tutte le lingue disponibili) ma non dovrebbe essere così prolisso.

Questa versione è sporca. Le eccezioni dovrebbero essere gestite, la lettura potrebbe essere migliorata. Questo è solo per mostrare come potrebbe iniziare una versione java.

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

Programma completo di seguito.

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

Esempio di output (usando il comando type)

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

Output di esempio (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

Prova qualsiasi

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

Modifica

Devo ammettere che non sono sicuro al 100% che si tratti del " best " modo di farlo. Sentiti libero di pubblicare riferimenti e / o codice per mostrare come può essere migliorato o cosa non va in questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top