Making a system call that returns the stdout outpu

2019-01-05 02:39发布

Perl and PHP do this with backticks. For example,

$output = `ls`;

Returns a directory listing. A similar function, system("foo"), returns the operating system return code for the given command foo. I'm talking about a variant that returns whatever foo prints to stdout.

How do other languages do this? Is there a canonical name for this function? (I'm going with "backtick"; though maybe I could coin "syslurp".)

27条回答
Rolldiameter
2楼-- · 2019-01-05 03:04

Lua:

    foo = io.popen("ls"):read("*a")
查看更多
Evening l夕情丶
3楼-- · 2019-01-05 03:05

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

With MissingH installed:

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

This is an easy operation in "glue" languages like Perl and Ruby, but Haskell isn't.

查看更多
我想做一个坏孩纸
4楼-- · 2019-01-05 03:05

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

查看更多
劫难
5楼-- · 2019-01-05 03:05

Perl, another way:

use IPC::Run3

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

Useful because you can feed the command input, and get back both stderr and stdout separately. Nowhere near as neat/scary/slow/disturbing as IPC::Run, which can set up pipes to subroutines.

查看更多
Viruses.
6楼-- · 2019-01-05 03:05

Granted, it is not the smaller ( from all the languages available ) but it shouldn't be that verbose.

This version is dirty. Exceptions should be handled, reading may be improved. This is just to show how a java version could start.

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

Complete program below.

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

Sample ouput ( using the type command )

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

Sample output ( 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

Try any

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

EDIT

I must admit I'm not 100% sure this is the "best" way to do it. Feel free to post references and/or code to show how can it be improved or what's wrong with this.

查看更多
看我几分像从前
7楼-- · 2019-01-05 03:07

Yet another way (or 2!) in Perl....

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

open can also be written like so...

open my $pipe, '-|', 'ps'
查看更多
登录 后发表回答