Pergunta

Perl e PHP fazer isso com acentos graves. Por exemplo,

$output = `ls`;

Retorna uma listagem de diretório. Uma função semelhante, system("foo"), retorna o código de retorno do sistema operacional para o dado foo comando. Estou falando de uma variante que retorna qualquer foo imprime em stdout.

Como outras línguas fazer isso? Existe um nome canônico para esta função? (Eu estou indo com "crase";. Embora talvez eu poderia cunhar "syslurp")

Foi útil?

Solução 20

Perl:

$output = `foo`;

ADICIONADO: Este é realmente um laço multi-caminho. A descrição acima é também válido em PHP e Ruby, por exemplo, usa a mesma notação backtick também.

Outras dicas

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 ou << a href =" http://docs.python.org/py3k/library/subprocess.html#subprocess.check_output" rel = "noreferrer"> 3.1

subprocess.check_output() Extrato de subprocess.py ou adaptar algo semelhante 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())

O subprocess módulo tem sido no stdlib desde 2.4.

Python:

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

[A pedido do Alexman e dreeves - ver comentários -, você vai encontrar neste DZones Java trechos página a versão completa Os-independente para fazer, neste caso, um 'ls'. Esta é uma resposta direta à sua código-desafio .
O que se segue abaixo é apenas o núcleo: Runtime.exec, mais 2 fios para ouvir stdout e stderr. ]

Java "simples!":

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

Ou no código java

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

Mas, para isso, você precisa de código ...
... isso é embaraçoso.

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

No entanto, outra maneira de fazê-lo em Perl (TIMTOWTDI)

$output = <<`END`;
ls
END

Isto é especialmente útil quando a incorporação de um shell script relativamente grande em um programa Perl

Ruby:. Quer backticks ou o '% x' builtin sintaxe

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

Um método alternativo em perl

$output = qx/ls/;

Este tinha a vantagem de que você pode escolher seus delimitadores, tornando possível usar o `no comando (embora IMHO você deveria reconsiderar o seu projeto se você realmente precisa fazer isso). Outra vantagem importante é que se você usar aspas simples como delimitador, variáveis ??não serão interpolados (muito útil)

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

Com MissingH instalado:

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

Esta é uma operação fácil em linguagens de "cola", como Perl e Ruby, mas Haskell não é.

No shell

OUTPUT=`ls`

ou alternativamente

OUTPUT=$(ls)

Este segundo método é melhor porque permite nidificação, mas não é suportado por todos os reservatórios, ao contrário do primeiro método.

Erlang:

os:cmd("ls")

Bem, uma vez que este é dependente do sistema, há muitas línguas que não têm um built-in wrapper para as várias chamadas de sistema necessários.

Por exemplo, Common Lisp em si não foi projetado para rodar em qualquer sistema específico. SBCL (Comum implementação Aço Banks Lisp), no entanto, não fornece uma extensão para Unix-like sistemas, como fazem a maioria das outras implementações CL. Isso é muito mais "poderoso" do que apenas começando a saída, é claro (você tem controle sobre o processo em execução, é possível especificar todos os tipos de direções de fluxo, etc., conferem ao manual do SBCL, capítulo 6.3), mas é fácil escrever um pequeno macro para esse fim específico:

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

Agora, você pode usá-lo como este:

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

Talvez você queira ingerir tudo em um string. A macro é trivial (embora código talvez mais concisa é possível):

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

Agora você pode obter uma string com esta chamada:

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

Mathematica:

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

Anos atrás eu escrevi um plug-in para jEdit que interface com uma aplicação nativa. Isto é o que eu usei para obter os fluxos fora do executável em execução. A única coisa que resta a fazer é 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;
    }
}

Não se esqueça Tcl:

set result [exec ls]

C # 3.0, menos detalhada do que esta :

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

Advertência: Código de produção deve descartar corretamente o objeto de processo ...

Contudo uma outra maneira (ou 2!) Em Perl ....

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

aberta também pode ser escrito assim ...

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

Em PHP

$output = `ls`;

ou

$output = shell_exec('ls');

C (com extensão 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;
}

Ok, não realmente concisa ou limpo. Assim é a vida em C ...

Em C em sistemas conformant Posix:

#include <stdio.h> 

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

Por que ainda não há um c # cara aqui:)

Esta é a forma de fazê-lo em C #. A built-in maneira.

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

    }
}

Aqui está outra maneira 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))

Então, para obter a sua string:

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

Se você deseja executar um comando que cria impressões uma grande quantidade de informação para STDOUT, você pode executá-lo como este:

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

O último parâmetro pré-aloca uma grande quantidade de espaço para a saída do grande escritor. Eu estou supondo que esta função poderia ser mais rápido do que ler a linha de fluxo de saída de cada vez.

Lua :

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

J :

output=:2!:0'ls'

Perl, de outra forma:

use IPC::Run3

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

útil porque você pode alimentar a entrada de comando, e voltar tanto stderr e stdout separadamente. Longe de ser tão puro / assustador / lento / perturbar como IPC::Run, que pode configurar tubos de sub-rotinas.

Ícone / Unicon:

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

Os docs chamar isso de uma tubulação. Uma das coisas boas é que faz o olhar de saída como você está apenas lendo um arquivo. Também significa que você pode escrever para stdin do aplicativo, se necessário.

Clozure Lisp comum:

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

Com certeza, não é o menor (de todos os idiomas disponíveis), mas ele não deve ser tão detalhado.

Esta versão está sujo. As exceções devem ser tratadas, a leitura pode ser melhorada. Este é apenas para mostrar como uma versão java poderia começar.

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

Programa completo abaixo.

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

ouput Amostra (usando o comando tipo)

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

Exemplo de saída (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

Tente qualquer

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

Editar

Devo admitir que eu não estou 100% certo de que este é o "melhor" maneira de fazê-lo. Sinta-se livre para postar referências e / ou código para mostrar como ela pode ser melhorada ou o que há de errado com isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top