dre*_*ves 16 language-agnostic terminology
Perl和PHP用反引号做到这一点.例如,
$output = `ls`;
Run Code Online (Sandbox Code Playgroud)
返回目录列表.类似的函数system("foo")返回给定命令foo的操作系统返回码.我在谈论一个将foo打印返回到stdout的变体.
其他语言如何做到这一点?这个函数有一个规范名称吗?(我要用"反击";但也许我可以用"syslurp"硬币.)
jfs*_*jfs 20
from subprocess import check_output as qx
output = qx(['ls', '-lt'])
Run Code Online (Sandbox Code Playgroud)
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())
Run Code Online (Sandbox Code Playgroud)
自2.4以来,子进程模块一直在stdlib中.
dre*_*ves 12
蟒蛇:
import os
output = os.popen("foo").read()
Run Code Online (Sandbox Code Playgroud)
[应Alexman和dreeves的请求- 请参阅评论 - ,您将在此DZones Java Snippet页面上找到完全版本的Os独立,在本例中为"ls".这是他们的代码挑战的直接答案.
下面的内容只是核心:Runtime.exec,加上2个线程来监听stdout和stderr.]
Java "简单!":
E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Executing cmd.exe /C dir *.java
...
Run Code Online (Sandbox Code Playgroud)
或者在java代码中
String output = GoodWindowsExec.execute("dir");
Run Code Online (Sandbox Code Playgroud)
但要做到这一点,你需要编码
......这是令人尴尬的.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
另一种在Perl中做到这一点的方法(TIMTOWTDI)
$output = <<`END`;
ls
END
Run Code Online (Sandbox Code Playgroud)
在Perl程序中嵌入相对较大的shell脚本时,这特别有用
perl中的另一种方法
$output = qx/ls/;
Run Code Online (Sandbox Code Playgroud)
这样做的好处是你可以选择你的分隔符,这样就可以在命令中使用`(尽管恕我直言,你应该重新考虑你的设计,如果你真的需要这样做).另一个重要的优点是,如果使用单引号作为分隔符,则不会插入变量(非常有用)
哈斯克尔:
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
Run Code Online (Sandbox Code Playgroud)
随着MissingH安装:
import System.Cmd.Utils
main = do
(pid, output) <- pipeFrom "ls" []
putStr output
forceSuccess pid
Run Code Online (Sandbox Code Playgroud)
这是一种像Perl和Ruby这样的"粘合"语言的简单操作,但Haskell不是.
在壳中
OUTPUT=`ls`
Run Code Online (Sandbox Code Playgroud)
或者
OUTPUT=$(ls)
Run Code Online (Sandbox Code Playgroud)
第二种方法更好,因为它允许嵌套,但与第一种方法不同,所有shell都不支持.
好吧,因为这是依赖于系统的,所以有许多语言没有内置的包装器来满足所需的各种系统调用.
例如,Common Lisp本身并不是为在任何特定系统上运行而设计的.然而,SBCL(Steel Banks Common Lisp实现)确实为类Unix系统提供了扩展,大多数其他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 = `foo`;
Run Code Online (Sandbox Code Playgroud)
补充:这确实是多方面的配合。上面的 PHP 也是有效的,例如 Ruby 也使用相同的反引号表示法。
| 归档时间: |
|
| 查看次数: |
12190 次 |
| 最近记录: |