我是靠谱客的博主 大胆砖头,最近开发中收集的这篇文章主要介绍如何用 scala 调用外部命令、重定向及使用管道?太长不看版正文,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

太长不看版

在 scala 中调用外部命令行程序非常简单,只需要导入 sys.process 包,并在需要调用的命令行外加双引号,并在行尾加 ! 号,如果想获得标准输出,就在行尾加 !! 号,如果需要管道或者重定向,请使用 #| 或者 #> 操作符,并注意在 #> 后面不能直接加文件名,需要使用 java.io.File 对象(关于如何快速运行 scala 交互式编程环境,请参考 如何利用 sbt 运行 Scala REPL )。举例:

// 导入需要的依赖
import sys.process._
import java.io.File
// 非阻塞式,使用 run 方法立即返回 scala.sys.process.Process 对象,并且外部命令同时执行
val process: Process = "ls -la".run
// 执行 ls -la 并且获取 exit code
val exitcode = "ls -la" !
// 执行 ls -la 并且获取标准输出
val stdout = "ls -la" !!
// 执行 ls -la . no_such_file.txt 并同时获取 exitcode,标准输出和标准错误
val n, e = new StringBuilder
val logger = ProcessLogger( l => n.append(l).append("n"), l => e.append(l).append("n"))
val exitcode = "ls -la . no_such_file.txt" ! logger
// bash 管道操作
val m = "ls -la" #| "grep foo" !!
// 输出重定向
"ls -la" #> new File("ls_output.txt") !

正文

我们在编写程序时经常会遇到需要在程序中调用外部命令的情况,scala 语言也提供了让程序员调用外部命令的功能。本文不但介绍如何在 scala 中调用外部命令行(比如 Linux 下的 bash 命令),也会讲解如何获取外部命令的标准输出、错误输出以及如何使用管道和重定向。关于如何快速运行 scala 交互式编程环境,请参考 如何利用 sbt 运行 Scala REPL

1.1 非阻塞式调用,获取 scala.sys.process.Process 对象

首先,导入 sys.process 包

scala> import sys.process._
import sys.process._

使用 run 方法获取进程对象

scala> val process: Process = "ls -la".run
process: scala.sys.process.Process = scala.sys.process.ProcessImpl$SimpleProcess@714975fd
total 24
drwxr-xr-x
7 kongl
staff
224 12 10 12:11 .
drwx------@ 458 kongl
staff
14656 12 10 12:11 ..
-rw-r--r--
1 kongl
staff
9 12 10 12:11 and_more.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 bar.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
drwxr-xr-x
3 kongl
staff
96 12 10 12:11 project
drwxr-xr-x
5 kongl
staff
160 12 10 12:17 target

1.2 在 scala 中调用外部命令并获取 exit code

首先,导入 sys.process 包

scala> import sys.process._
import sys.process._

在需要调用的命令行外加双引号,并在行尾加 ! 号

scala> val exitcode = "ls -al" !
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
total 24
drwxr-xr-x
7 kongl
staff
224 12 10 12:11 .
drwx------@ 458 kongl
staff
14656 12 10 12:11 ..
-rw-r--r--
1 kongl
staff
9 12 10 12:11 and_more.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 bar.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
drwxr-xr-x
3 kongl
staff
96 12 10 12:11 project
drwxr-xr-x
5 kongl
staff
160 12 10 12:17 target
exitcode: Int = 0
scala> print(exitcode)
0

2. 在 scala 中调用外部命令并获取标准输出和错误输出

2.1 只需要获取标准输出的情形

如果只需要标准输出,那么非常简单,只需要把上个例子中的 ! 替换为 !! 即可,例如

scala> import sys.process._
import sys.process._
scala> val stdout = "ls -la" !!
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
stdout: String =
"total 24
drwxr-xr-x
7 kongl
staff
224 12 10 12:23 .
drwx------@ 458 kongl
staff
14656 12 10 12:11 ..
-rw-r--r--
1 kongl
staff
9 12 10 12:11 and_more.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 bar.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
drwxr-xr-x
4 kongl
staff
128 12 10 12:31 project
drwxr-xr-x
5 kongl
staff
160 12 10 12:17 target
"
scala> print(stdout)
total 24
drwxr-xr-x
7 kongl
staff
224 12 10 12:23 .
drwx------@ 458 kongl
staff
14656 12 10 12:11 ..
-rw-r--r--
1 kongl
staff
9 12 10 12:11 and_more.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 bar.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
drwxr-xr-x
4 kongl
staff
128 12 10 12:31 project
drwxr-xr-x
5 kongl
staff
160 12 10 12:17 target

2.2 需要同时获取标准输出和错误输出的情形

如果需要同时获取标准输出和错误输出,那我们需要用到 ProcessLogger 类,例如

scala> import sys.process._
import sys.process._
scala> val n, e = new StringBuilder
n: StringBuilder =
e: StringBuilder =
scala> val logger = ProcessLogger( l => n.append(l).append("n"), l => e.append(l).append("n"))
logger: scala.sys.process.ProcessLogger = scala.sys.process.ProcessLogger$$anon$1@25968d9c
scala> val exitcode = "ls -la . no_such_file.txt" ! logger
exitcode: Int = 1
scala> print(exitcode)
1
scala> print(n)
.:
total 24
drwxr-xr-x
7 kongl
staff
224 12 10 12:23 .
drwx------@ 458 kongl
staff
14656 12 10 12:11 ..
-rw-r--r--
1 kongl
staff
9 12 10 12:11 and_more.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 bar.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
drwxr-xr-x
4 kongl
staff
128 12 10 12:31 project
drwxr-xr-x
5 kongl
staff
160 12 10 12:17 target
scala> print(e)
ls: no_such_file.txt: No such file or directory

3. 使用管道和重定向

3.1 如何使用管道

在 scala 中调用 shell 命令,我们不能直接在命令行中使用管道,这是因为 scala 在调用命令时并不会启动 bash 环境,而管道和重定向是 bash 支持的功能。例如,直接运行 “ls -la | grep foo” 我们得到如下报错信息:

scala> import sys.process._
import sys.process._
scala> "ls -la | grep foo" !!
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
ls: foo: No such file or directory
ls: grep: No such file or directory
ls: |: No such file or directory
java.lang.RuntimeException: Nonzero exit value: 1
at scala.sys.package$.error(package.scala:30)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:138)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:108)
... 36 elided

因此,我们需要使用 scala 语言提供的 #| 操作符,例如:

scala> val m = "ls -la" #| "grep foo" !!
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
m: String =
"-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
"
scala> print(m)
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt

也可以多个 #! 连用,例如

scala> val m = "ls -la" #| "grep txt" #| "wc -l" !!
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
m: String =
"
3
"
scala> print(m)
3

3.2 如何使用重定向

和使用管道类似,scala 为标准输出重定向提供了 #> 操作符,需要注意的是,在 #> 后面不能直接加文件名,需要使用 File 对象,例如:

scala> import sys.process._
import sys.process._
scala> import java.io.File
import java.io.File
scala> "ls -la" #> new File("ls_output.txt") !
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
res31: Int = 0
scala> "cat ls_output.txt" !!
warning: there was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
res32: String =
"total 24
drwxr-xr-x
8 kongl
staff
256 12 10 15:28 .
drwx------@ 458 kongl
staff
14656 12 10 12:11 ..
-rw-r--r--
1 kongl
staff
9 12 10 12:11 and_more.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 bar.txt
-rw-r--r--
1 kongl
staff
12 12 10 12:11 foo.txt
-rw-r--r--
1 kongl
staff
0 12 10 15:28 ls_output.txt
drwxr-xr-x
4 kongl
staff
128 12 10 12:31 project
drwxr-xr-x
5 kongl
staff
160 12 10 12:17 target
"

3.3 其他 bash 操作符对应

#<
输入重定向
#>
输出重定向
#>>
追加输出重定向
#&&
和
#!!
或

参考链接

  1. How to execute (exec) external system commands in Scala
  2. Scala: How to handle the STDOUT and STDERR of external commands
  3. ProcessLogger

最后

以上就是大胆砖头为你收集整理的如何用 scala 调用外部命令、重定向及使用管道?太长不看版正文的全部内容,希望文章能够帮你解决如何用 scala 调用外部命令、重定向及使用管道?太长不看版正文所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部