Question

Perl et PHP le font avec des backticks. Par exemple,

$output = `ls`;

Renvoie une liste de répertoires. Une fonction similaire, system("foo"), renvoie le code de retour du système d’exploitation pour la commande donnée foo. Je parle d'une variante qui renvoie tout ce que foo affiche sur stdout.

Comment les autres langues font-elles cela? Existe-t-il un nom canonique pour cette fonction? (J'y vais avec & "; Un backtick &"; Mais je pourrais peut-être inventer & "Syslurp &";).

Était-ce utile?

La solution 20

Perl:

$output = `foo`;

ADDED: C’est vraiment une cravate à plusieurs. Ce qui précède est également valide en PHP, et Ruby, par exemple, utilise également la même notation backtick.

Autres conseils

Python

from subprocess import check_output as qx

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

Python < 2.7 ou lt; 3.1

Extrait subprocess.check_output() de subprocess.py ou adapter quelque chose de similaire à:

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

Le module du sous-processus est dans la stdlib depuis la version 2.4.

Python:

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

[À la demande de Alexman et dreeves - voir les commentaires -, vous trouverez à cet Page d'extraits de code Java de DZones , version complète indépendante du système d'exploitation permettant de définir, dans ce cas, un" ls ". Ceci est une réponse directe à leur code-challenge .
Ce qui suit est juste le noyau: Runtime.exec, plus 2 threads pour écouter stdout et stderr. ]

Java & "Simple! &":

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

Ou en code java

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

Mais pour cela, vous devez coder ...
... c'est embarrassant.

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

Encore une autre façon de le faire en Perl (TIMTOWTDI)

$output = <<`END`;
ls
END

Ceci est particulièrement utile pour incorporer un script shell relativement volumineux dans un programme Perl

Ruby: des backticks ou la syntaxe intégrée '% x'.

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

Une méthode alternative en perl

$output = qx/ls/;

Cela présentait l’avantage de pouvoir choisir vos délimiteurs, ce qui rendait possible l’utilisation de `dans la commande (même à mon humble avis, vous devriez reconsidérer votre conception si vous en avez vraiment besoin). Un autre avantage important est que si vous utilisez des guillemets simples comme délimiteur, les variables ne seront pas interpolées (très utile)

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

Avec MissingH installé:

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

C’est une opération facile avec & "; colle &"; langages comme Perl et Ruby, mais pas Haskell.

En shell

OUTPUT=`ls`

ou alternativement

OUTPUT=$(ls)

Cette deuxième méthode est préférable car elle permet l'imbrication, mais n'est pas prise en charge par tous les shells, contrairement à la première méthode.

Erlang:

os:cmd("ls")

Etant donné que cela dépend du système, de nombreuses langues n’ont pas d’encapsuleur intégré pour les divers appels système nécessaires.

Par exemple, Common Lisp n'a pas été conçu pour fonctionner sur un système spécifique. SBCL (implémentation Common Banks Lisp en acier), cependant, fournit une extension pour les systèmes de type Unix, comme le font la plupart des autres implémentations CL. C’est beaucoup plus & Quot; puissant & Quot; Bien sûr, il ne suffit pas d’obtenir le résultat (vous avez le contrôle du processus en cours, vous pouvez spécifier toutes sortes de directions de flux, etc., reportez-vous au manuel SBCL, chapitre 6.3), mais il est facile d’écrire une petite macro pour cela. but:

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

Maintenant, vous pouvez l'utiliser comme ceci:

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

Peut-être voulez-vous le glisser dans une chaîne. La macro est triviale (mais un code plus concis est peut-être possible):

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

Vous pouvez maintenant obtenir une chaîne avec cet appel:

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

Mathematica:

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

Il y a des années, j'ai écrit un plug-in pour jEdit qui s'interface avec une application native. C’est ce que j’utilisais pour extraire les flux de l’exécutable en cours d’exécution. La seule chose qui reste à faire est 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'oubliez pas Tcl:

set result [exec ls]

C # 3.0, moins commenté que celui-ci :

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

Avertissement: le code de production doit disposer correctement de l'objet Processus ...

Encore une autre façon (ou 2!) en Perl ....

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

ouvert peut également être écrit de la manière suivante ...

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

En PHP

$output = `ls`;

ou

$output = shell_exec('ls');

C (avec glibc extension):

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

D'accord, pas vraiment concis ou propre. C'est la vie en C ...

Systèmes conformes C sur Posix:

#include <stdio.h> 

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

Pourquoi n'y a-t-il toujours pas de gars c # ici:)

Voici comment procéder en C #. La manière intégrée.

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

    }
}

Voici un autre moyen 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))

Ensuite, pour obtenir votre chaîne:

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

Si vous souhaitez exécuter une commande qui crée imprime de nombreuses informations sur STDOUT, vous pouvez l'exécuter comme suit:

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

Le dernier paramètre préalloue une grande quantité d’espace pour la sortie de Big-writer. Je suppose que cette fonction pourrait être plus rapide que la lecture du flux de sortie ligne par ligne.

Lua :

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

J :

output=:2!:0'ls'

Perl, une autre manière:

use IPC::Run3

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

Utile car vous pouvez alimenter l'entrée de commande et récupérer séparément stderr et stdout. Nulle part près aussi net / effrayant / lent / dérangeant que IPC::Run, qui peut installer des tuyaux vers des sous-programmes.

Icône / Unicon:

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

Les docs appellent cela un pipe. L’un des avantages est que la sortie donne l’impression que vous lisez un fichier. Cela signifie également que vous pouvez écrire sur le stdin de l'application, si vous devez.

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

Certes, ce n'est pas le plus petit (de toutes les langues disponibles) mais il ne devrait pas être aussi prolixe.

Cette version est sale. Les exceptions doivent être traitées, la lecture peut être améliorée. Ceci est juste pour montrer comment une version java pourrait démarrer.

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

Programme complet ci-dessous.

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

Exemple de sortie (à l'aide de la commande type)

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

Exemple de sortie (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

Essayez n'importe quel

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

MODIFIER

Je dois admettre que je ne suis pas sûr à 100% que ce soit le & "meilleur &"; façon de le faire. N'hésitez pas à poster des références et / ou du code pour montrer comment il peut être amélioré ou ce qui ne va pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top