문제

Perl과 PHP는 백틱을 사용하여 이를 수행합니다.예를 들어,

$output = `ls`;

디렉토리 목록을 반환합니다.비슷한 기능, system("foo"), 주어진 명령 foo에 대한 운영 체제 반환 코드를 반환합니다.나는 foo가 인쇄한 모든 것을 stdout으로 반환하는 변형에 대해 이야기하고 있습니다.

다른 언어에서는 이를 어떻게 수행합니까?이 함수에 대한 정식 이름이 있나요?(저는 "백틱"을 사용하겠습니다.하지만 "syslurp"라는 이름을 붙일 수도 있겠네요.)

도움이 되었습니까?

해결책 20

perl :

$output = `foo`;

추가 : 이것은 실제로 멀티 웨이 넥타이입니다. 위는 또한 유효한 PHP이며, 예를 들어 Ruby는 동일한 백티크 표기법도 사용합니다.

다른 팁

파이썬

from subprocess import check_output as qx

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

파이썬2.7 또는3.1

발췌 subprocess.check_output() ~에서 하위 프로세스 .py 또는 다음과 유사한 것을 조정합니다.

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

그만큼 하위 프로세스 모듈은 2.4 이후 stdlib에 있습니다.

파이썬 :

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

의 요청 알렉스맨 그리고 드레이브스 -댓글을 참조하십시오-, 당신은 이것에서 찾을 수 있습니다 Dzones Java Snippet 페이지 이 경우 'ls'를 만들기위한 정식 버전 OS 독립적입니다. 이것은 그들의 직접적인 답입니다 Code-Challenge.
다음은 핵심 핵심입니다 : runtime.exec, 그리고 stdout과 stderr를들을 수있는 2 개의 스레드입니다. ]

자바 "단순한!":

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

또는 Java 코드로

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

그러나 그렇게하려면 코딩해야합니다 ...
... 이건 창피해.

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

Perl에서 그것을하는 또 다른 방법 (Timtowtdi)

$output = <<`END`;
ls
END

이것은 PERL 프로그램에 비교적 큰 쉘 스크립트를 포함시킬 때 특히 유용합니다.

루비 : 백 티크 또는 '%X'내장 구문.

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

Perl의 대체 방법

$output = qx/ls/;

이것은 구분자를 선택할 수 있다는 이점이 있었기 때문에`명령에서`를 사용할 수 있습니다 (IMHO는 실제로 필요한 경우 디자인을 재고해야합니다). 또 다른 중요한 장점은 단일 따옴표를 구분 기자로 사용하는 경우 변수가 보간되지 않는다는 것입니다 (매우 유용함).

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

와 함께 누락 설치 :

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

이것은 Perl 및 Ruby와 같은 "접착제"언어에서 쉽게 작동하지만 Haskell은 그렇지 않습니다.

쉘에서

OUTPUT=`ls`

또는 대안 적으로

OUTPUT=$(ls)

이 두 번째 방법은 중첩을 허용하기 때문에 더 좋습니다. 그러나 첫 번째 방법과 달리 모든 쉘에서 지원하지는 않습니다.

Erlang :

os:cmd("ls")

글쎄, 이것은 시스템에 따라 다르기 때문에 필요한 다양한 시스템 호출을 위한 내장 래퍼가 없는 언어가 많이 있습니다.

예를 들어 Common Lisp 자체는 특정 시스템에서 실행되도록 설계되지 않았습니다.그러나 SBCL(Steel Banks Common Lisp 구현)은 대부분의 다른 CL 구현과 마찬가지로 Unix 계열 시스템에 대한 확장을 제공합니다.물론 이는 단순히 출력을 얻는 것보다 훨씬 더 "강력"합니다(실행 중인 프로세스를 제어할 수 있고 모든 종류의 스트림 방향 등을 지정할 수 있으며 SBCL 매뉴얼, 6.3장 참조). 이 특정 목적을 위해 작은 매크로를 작성하십시오.

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

이제 다음과 같이 사용할 수 있습니다.

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

아마도 당신은 이 모든 것을 하나의 문자열로 후루룩 마시고 싶을 것입니다.매크로는 간단합니다(더 간결한 코드도 가능하지만).

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

이제 다음 호출로 문자열을 얻을 수 있습니다.

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

수학 :

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

몇 년 전에 나는 a 플러그인 ~을 위한 제다트 그것은 기본 응용 프로그램에 인터페이스되었습니다. 이것이 제가 실행 실행 파일에서 스트림을 제거하는 데 사용한 것입니다. 남은 일은 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;
    }
}

TCL을 잊지 마세요 :

set result [exec ls]

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

경고 : 프로덕션 코드는 프로세스 개체를 올바르게 처분해야합니다 ...

Perl에서 또 다른 방법 (또는 2!) ....

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

열려 있는 그렇게 쓸 수 있습니다 ...

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

PHP에서

$output = `ls`;

또는

$output = shell_exec('ls');

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의 삶입니다 ...

Posix 준수 시스템의 C에서 :

#include <stdio.h> 

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

여기에 아직 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);
        }

    }
}

또 다른 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)

마지막 매개 변수는 큰 작가의 출력을위한 많은 양의 공간을 경쟁합니다. 이 기능이 출력 스트림을 한 번에 한 줄 씩 읽는 것보다 빠를 수 있다고 생각합니다.

루아:

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

제이:

output=:2!:0'ls'

Perl, 다른 방법 :

use IPC::Run3

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

명령 입력을 공급하고 STDERR과 STDOUT를 별도로 다시 얻을 수 있기 때문에 유용합니다. 깔끔한/무서운/느리게/방해가되지 않습니다. IPC::Run, 서브 루틴에 파이프를 설정할 수 있습니다.

아이콘/유니콘 :

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

문서는 이것을 파이프라고 부릅니다. 좋은 점 중 하나는 파일을 읽는 것처럼 출력을 보이게한다는 것입니다. 또한 앱의 stdin에 쓸 수 있음을 의미합니다.

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

물론, 그것은 더 작지는 않지만 (사용 가능한 모든 언어에서) 그 장황해서는 안됩니다.

이 버전은 더럽습니다. 예외를 처리해야하며 읽기가 향상 될 수 있습니다. 이것은 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();
    }
}

샘플 OUPUT (유형 명령 사용)

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"

편집하다

나는 이것이 "가장 좋은"방법이라고 확신하지 않다는 것을 인정해야한다. 참조 및/또는 코드를 게시하여 어떻게 개선 할 수 있는지 또는 무엇이 잘못되었는지 보여주십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top