Making a system call that returns the stdout output as a string

前端 未结 27 858
误落风尘
误落风尘 2020-11-27 05:13

Perl and PHP do this with backticks. For example,

$output = `ls`;

Returns a directory listing. A similar function, system(\"foo\")

相关标签:
27条回答
  • 2020-11-27 05:50

    C (with 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;
    }
    

    Okay, not really concise or clean. That's life in C...

    0 讨论(0)
  • 2020-11-27 05:50

    Here's another Lisp way:

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

    Then, to get your string:

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

    If you want to run a command that creates prints a great deal of info to STDOUT, you can run it like this:

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

    The last parameter preallocates a large amount of space for the output from big-writer. I'm guessing this function could be faster than reading the output stream one line at a time.

    0 讨论(0)
  • 2020-11-27 05:51

    In PHP

    $output = `ls`;
    

    or

    $output = shell_exec('ls');
    
    0 讨论(0)
  • 2020-11-27 05:52

    Well, since this is system dependent, there are many languages that do not have a built-in wrapper for the various system calls needed.

    For example, Common Lisp itself was not designed to run on any specific system. SBCL (the Steel Banks Common Lisp implementation), though, does provide an extension for Unix-like systems, as do most other CL implementations. This is much more "mighty" than just getting the output, of course (you have control over the running process, can specify all kinds of stream directions, etc., confer to the SBCL manual, chapter 6.3), but it is easy to write a little macro for this specific purpose:

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

    Now, you can use it like this:

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

    Perhaps you want to slurp it all into one string. The macro is trivial (though perhaps more concise code is 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)))))))
    

    Now you can get a string with this call:

    (syslurp "ls" '("-l"))
    0 讨论(0)
  • 2020-11-27 05:53

    In C on Posix conformant systems:

    #include <stdio.h> 
    
    FILE* stream = popen("/path/to/program", "rw");
    fprintf(stream, "foo\n"); /* Use like you would a file stream. */
    fclose(stream);
    
    0 讨论(0)
  • 2020-11-27 05:53

    Perl:

    $output = `foo`;
    

    ADDED: This is really a multi-way tie. The above is also valid PHP, and Ruby, for example, uses the same backtick notation as well.

    0 讨论(0)
提交回复
热议问题