【问题标题】:How can I supply input for an external command?如何为外部命令提供输入?
【发布时间】:2014-04-14 15:53:04
【问题描述】:

据我了解,Scala 可以运行系统命令并接收它们的输出。我正在为我拥有的系统命令编写一个 Web 客户端,所以据说我需要执行命令,接收输出,根据输出我可以给它一个命令。我想继续这样做,直到用户终止命令。我已经阅读了一些关于 ProcessIO 的内容,并且我已经获得了从 scala 运行命令并接收输出的信息,但是我怎样才能给它输入呢?

编辑: 我正在寻找的是,我用 scala 调用命令。我调用的命令要求输入,用户将输入提供给 scala 程序,然后将其传递给被调用的程序。

一个例子:

Scala 程序 -> 调用系统程序 -> 系统程序询问用户名和密码 -> Scala 程序程序然后向用户询问用户名和密码,用户提供输入 -> Scala 程序将输入传递给系统程序。

我想在给它输入的同时保持进程活着。

【问题讨论】:

  • 您能否提供更多有关您要完成的工作的详细信息?
  • 我想你需要的都在这里:*.com/questions/7195051/…
  • 考虑对此问题的更新答案。非常感谢。

标签: scala


【解决方案1】:

考虑以下带有重定向的示例,

import scala.sys.process._
import java.io.File

"""echo -e hello\nworld""" #> new File("hello") !

new File ("hello") #> """grep world -c""" !!

提供1

这会将一个回显的字符串写入一个输出文件;接下来将现在的 input 文件重定向到系统命令。

更新

命令

"""echo -e hello\nworld""" #> """grep world -c""" !!

使用重定向并将结果作为字符串传递。这样可以避免中间文件。

【讨论】:

  • 因此,使用此解决方案,我将让 scala 程序将用户输入写入文件,然后我需要一个中间人进程来打开文件获取输入并将其提供给系统程序?
  • 这会杀死进程吗?
【解决方案2】:

我无法从您的问题中判断您是否打算让用户向控制台提供除标准输入以外的其他输入。虽然我怀疑您希望它“完全包含”在 Scala 程序中,但我还没有解决这个问题。然而,如果使用控制台是可以接受的,这里有一个简单的 Scala 程序示例,它要求输入用户名/密码,另一个 Scala 程序启动它并使用Process.run(true) 将调用程序的 out/err 连接到控制台,而输入可以提供给控制台。

SimpleProgram 用于测试输入:

package so

import java.util.Scanner

object SimpleProgram extends App {

  def getInput(prompt: String): Option[String] = {
    print( s"$prompt: " )
    val sc = new Scanner(System.in)
    sc.hasNextLine match {
      case true => val out = sc.nextLine
        if( out.length > 1 ) Some(out) else None
      case _ => None
    }
  }

  while( true ) {
    (getInput("username"), getInput("password")) match {
      case (Some(u), Some(p)) => println( s"Logged in as $u" ); System.exit(0)
      case _ => println( "Invalid input.  Please try again." )
    }
  }
}

这是调用 ProcessBuilder 的程序(类路径在没有更改的情况下无法工作):

package so

import scala.sys.process._

object ProcessBuilderTest extends App {

  val classpath = "<path to>/scala-library.jar:./classes"
  val pb = Process("java", Seq("-cp", classpath, "so.SimpleProgram" ))
  pb.run(true) // all the magic happens here.
}

在这种情况下,Process 基本上只是将调用的程序包装在ProcessBuilder 中。我无法使用 ProcessIO 和提供的方法来解决问题,既吃掉适当的字符,又杀死流等。我的猜测是,查看工作中的 run(true) 案例会很有启发性。

以下是控制台日志记录的示例,该示例使用更正的类路径运行后者:

username: foo
password: 
Invalid input.  Please try again.
username: foo
password: bar
Logged in as foo

我正在使用“java”来运行 Scala 代码,因为除了通过 Eclipse 之外,我的 Mac 上没有安装 Scala。在 Eclipse 中,ProcessBuilderTest 是从项目目录中运行的,其中包含两个类,并且输出目录设置为“classes”而不是“bin”。

【讨论】: