Выполнение системного вызова, который возвращает вывод stdout в виде строки - PullRequest
16 голосов
/ 25 октября 2008

Perl и PHP делают это с помощью обратных кавычек. Например,

$output = `ls`;

Возвращает список каталогов. Аналогичная функция system("foo") возвращает код возврата операционной системы для данной команды foo. Я говорю о варианте, который возвращает любой вывод foo на стандартный вывод.

Как другие языки делают это? Есть ли каноническое имя для этой функции? (Я собираюсь использовать "backtick"; хотя, возможно, я мог бы написать "syslurp")

Ответы [ 27 ]

3 голосов
/ 03 сентября 2009

Lua

    foo = io.popen("ls"):read("*a")
3 голосов
/ 17 декабря 2008

In C в системах, соответствующих требованиям Posix:

#include <stdio.h> 

FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);
2 голосов
/ 23 декабря 2008

Значок / Юникон:

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

Документы называют это трубкой. Одна из хороших вещей - это то, что вывод выглядит так, будто вы просто читаете файл. Это также означает, что вы можете написать в stdin приложения, если необходимо.

2 голосов
/ 16 декабря 2008

Perl, другой способ:

use IPC::Run3

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

Полезно, потому что вы можете подать ввод команды и получить как stderr, так и stdout отдельно. Нигде не так аккуратно / страшно / медленно / тревожно, как IPC::Run, что может настроить каналы для подпрограмм.

2 голосов
/ 03 сентября 2009

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))
2 голосов
/ 28 октября 2008

J

output=:2!:0'ls'
0 голосов
/ 17 декабря 2008

Конечно, он не меньше (из всех доступных языков), но не должен быть таким многословным.

Эта версия грязная. Исключения должны быть обработаны, чтение может быть улучшено. Это просто для того, чтобы показать, как может начинаться 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 );
}

Завершите программу ниже.

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

Пример вывода (с помощью команды type)

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

Пример вывода (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

Попробуйте любой

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

EDIT

Должен признать, я не уверен на 100%, что это "лучший" способ сделать это. Не стесняйтесь размещать ссылки и / или код, чтобы показать, как его можно улучшить или что с этим не так.

...