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

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

$output = `ls`;

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

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

Ответы [ 27 ]

4 голосов
/ 26 октября 2008

Еще один способ (или 2!) В Perl ....

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

open также можно записать так ...

open my $pipe, '-|', 'ps'
4 голосов
/ 02 декабря 2008

Не забудьте Tcl:

set result [exec ls]
4 голосов
/ 11 января 2009

C # 3.0, менее многословно, чем этот :

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

Предупреждение: производственный код должен правильно располагать объект Process ...

4 голосов
/ 31 октября 2008

Несколько лет назад я написал плагин для jEdit , который взаимодействовал с нативным приложением. Это то, что я использовал для получения потоков от исполняемого файла. Осталось только сделать while((String s = stdout.readLine())!=null){...}:

<code>/* 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();
     *  
* * @return Значение процесса * / public Process getProcess () { вернуть this.process; } }
4 голосов
/ 25 октября 2008

Mathematica:

output = Import["!foo", "Text"];
3 голосов
/ 25 октября 2008

В PHP

$output = `ls`;

или

$output = shell_exec('ls');
3 голосов
/ 03 сентября 2009

Вот еще один способ 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))

Затем, чтобы получить вашу строку:

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

Если вы хотите запустить команду, которая создает распечатки большого количества информации, в STDOUT, вы можете запустить ее так:

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

Последний параметр предварительно выделяет большое количество места для вывода из большого писателя. Я предполагаю, что эта функция может быть быстрее, чем чтение выходного потока по одной строке за раз.

3 голосов
/ 28 октября 2008

C (с расширением 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;
}

Хорошо, не совсем кратко или чисто. Это жизнь в C ...

3 голосов
/ 25 октября 2008

Perl:

$output = `foo`;

ДОБАВЛЕНО: Это действительно многопрофильный галстук. Вышеприведенный код также является действительным PHP, и Ruby, например, также использует ту же нотацию обратного знака.

3 голосов
/ 23 декабря 2008

Почему до сих пор нет парня c # здесь:)

Вот как это сделать в C #. Встроенный способ.

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

    }
}
...