سؤال

تقوم Perl وPHP بذلك باستخدام علامات الرجوع.على سبيل المثال،

$output = `ls`;

إرجاع قائمة الدليل.وظيفة مماثلة، system("foo"), ، يقوم بإرجاع رمز إرجاع نظام التشغيل للأمر المحدد foo.أنا أتحدث عن متغير يقوم بإرجاع أي طباعة foo إلى stdout.

كيف تفعل اللغات الأخرى هذا؟هل هناك اسم متعارف عليه لهذه الوظيفة؟(سأختار "backtick"؛على الرغم من أنه ربما يمكنني صياغة "syslurp".)

هل كانت مفيدة؟

المحلول 20

وبيرل:

$output = `foo`;

وأضاف: هذا هو حقا متعددة طريقة التعادل. ما سبق هو أيضا PHP صحيح، وروبي، على سبيل المثال، يستخدم نفس الفاصلة العليا المائلة تدوين كذلك.

نصائح أخرى

بيثون

from subprocess import check_output as qx

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

بيثون << لأ href = "http://docs.python.org/dev/library/subprocess.html#subprocess.check_output" يختلط = "noreferrer"> 2.7 أو << لأ href = " http://docs.python.org/py3k/library/subprocess.html#subprocess.check_output "يختلط =" noreferrer "> 3.1

واستخراج subprocess.check_output() من subprocess.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())

فرعي أو جانبي وحدة كانت في stdlib منذ 2.4.

وبيثون:

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

[بناء على طلب من أليكسمان و دريفز -- انظر التعليقات --، ستجد في هذا صفحة مقتطف جافا DZones نسخة كاملة مستقلة عن نظام التشغيل لإنشاء، في هذه الحالة، 'ls'.وهذا رد مباشر عليهم تحدي الكود.
ما يلي أدناه هو مجرد جوهر:Runtime.exec، بالإضافة إلى 2 موضوع للاستماع إلى stdout وstderr.]

جافا "بسيط!":

E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Executing cmd.exe /C dir *.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;
    }
}

وطريقة أخرى للقيام بذلك في بيرل (TIMTOWTDI)

$output = <<`END`;
ls
END

وهذا مفيد بشكل خاص عند تضمين شيل كبير نسبيا في برنامج بيرل

وروبي: إما backticks أو '٪ س' جملة مدمج

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

وهناك طريقة بديلة في بيرل

$output = qx/ls/;

وكان لهذا ميزة أنه يمكنك اختيار المحددات الخاصة بك، مما يجعل من الممكن استخدام `في الأمر (على الرغم IMHO يجب إعادة النظر في التصميم الخاص بك إذا كنت حقا بحاجة للقيام بذلك). ميزة أخرى مهمة هي أنه إذا كنت تستخدم علامات الاقتباس المفردة كما محدد، لن محرف المتغيرات (مفيد جدا)

وحزقيل:

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

MissingH مثبتة:

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

وهذا هو عملية سهلة لغات "الغراء" مثل بيرل وروبي، ولكن هاسكل ليست كذلك.

في قذيفة

OUTPUT=`ls`

وأو بدلا من ذلك

OUTPUT=$(ls)

وهذه الطريقة الثانية هي أفضل لأنه يسمح تداخل، ولكن غير معتمد من قبل جميع قذائف، على عكس الأسلوب الأول.

وإرلانج:

os:cmd("ls")

حسنا، لأن هذا هو نظام يعتمد، هناك العديد من اللغات التي ليس لديها المدمج في مجمع لدعوات النظام المختلفة اللازمة.

وعلى سبيل المثال، اللثغة المشتركة نفسها لم تكن مصممة لتعمل على أي نظام معين. SBCL (الصلب البنوك تنفيذ اللثغة المشتركة)، على الرغم من لا توفر امتدادا لأنظمة يونكس مثل، كما تفعل تطبيقات CL الأكثر الأخرى. وهذا هو أكثر من ذلك بكثير "الأقوياء" من مجرد الحصول على المخرجات، وبطبيعة الحال (لديك السيطرة على عملية التشغيل، يمكنك تحديد جميع أنواع الاتجاهات تيار، وما إلى ذلك، منح لدليل 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"];

وقبل سنوات كنت كتبت المساعد للحصول على <لأ href = "http://jedit.org "يختلط =" نوفولو noreferrer "> جيديت أن ربطه إلى التطبيق الأصلي. هذا ما اعتدت على تيارات قبالة تنفيذ التوالي. الشيء الوحيد الذي غادر الى القيام به هو 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;
    }
}

ولا ننسى تى سى ال:

set result [exec ls]

وC # 3.0، أقل مطول من <لأ href = "https://stackoverflow.com/questions/236737/language-showdown-how-do-you-make-a-system-call-that-returns-the- المعياري والمخرجات واحد # 388176 "> هذا واحد :

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

والتحذير: كود الإنتاج يجب التخلص السليم الكائن عملية ...

وطريقة أخرى (أو 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 ...

في 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);

لماذا لا يزال هناك ج # الرجل هنا:)

وهذه هي الطريقة للقيام بذلك في 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);
        }

    }
}

وهنا طريقة ليسب آخر:

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

والمعلمة الأخيرة preallocates كمية كبيرة من مساحة لإخراج من الكاتب الكبير. انا التخمين هذه الوظيفة يمكن أن تكون أسرع من قراءة دفق إخراج سطر واحد في وقت واحد.

لوا :

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

J :

output=:2!:0'ls'

وبيرل، وسيلة أخرى:

use IPC::Run3

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

ومفيد لأنه يمكنك إطعام إدخال الأوامر، ونعود كلا ستدير والمعياري بشكل منفصل. أي مكان بالقرب من أنيق / مخيفة / بطيئة / إزعاج كما IPC::Run، التي يمكن إعداد أنابيب إلى الوظائف الفرعية.

أيقونة / يونيكون:

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

وومستندات تدعو هذه الأنابيب. واحدة من الأشياء الجيدة هو أنه يجعل نظرة الانتاج وكأنك مجرد قراءة ملف. وهذا يعني أيضا يمكنك الكتابة إلى ستدين التطبيق، إذا كنت لا بد منه.

وClozure اللثغة المشتركة:

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

من المؤكد أنها ليست الأصغر حجمًا (من جميع اللغات المتاحة) ولكن لا ينبغي أن تكون مطولة إلى هذا الحد.

هذا الإصدار قذر.ينبغي التعامل مع الاستثناءات، ويمكن تحسين القراءة.هذا فقط لإظهار كيف يمكن أن يبدأ إصدار جافا.

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

إخراج العينة (باستخدام أمر الكتابة)

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

إخراج العينة (دير)

 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"

يحرر

يجب أن أعترف أنني لست متأكدًا بنسبة 100% من أن هذه هي الطريقة "الأفضل" للقيام بذلك.لا تتردد في نشر المراجع و/أو التعليمات البرمجية لإظهار كيف يمكن تحسينها أو ما هو الخطأ في هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top