如何在Scala中进行Bash进程替换?

时间:2016-08-04 22:19:19

标签: scala

如何在Scala中完成diff <(echo aoeu) <(echo snth)这样的事情?

我已尝试使用https://forum.ionicframework.com/t/google-map-inside-ion-slides-display-issue/53743/2,如下所示:

"diff <(echo aoeu) <(echo snth)".!

...但是,这并不能将<()解释为子流程替换。

1 个答案:

答案 0 :(得分:3)

import scala.sys.process._

def diff(one: String, two: String):
  String = Seq(
    "bash", "-c", """
       diff <(printf '%s\n' "$1") \
            <(printf '%s\n' "$2"); retval=$?
       (( retval == 1 )) || exit "$retval"
    """, "_", one, two).!!

这可以在实践中进行测试:

scala> diff("hello", "world")
res1: String =
"1c1
< hello
---
> world
"

打破推理:

  • 调用序列而不是字符串,允许数据(在我的示例中helloworld;在您的aoeusnth中)传递出来 - 来自代码的乐队。这对于在参数化此类内容时避免injection attacks至关重要。
  • 调用bash作为可执行文件可确保process substitution语法可用。
  • 检查退出状态为1(并将其强制为0)可避免scala处理diff返回退出状态的情况,表明两个输入不同于错误,同时确保其他错误仍然存​​在在scala中成为例外。
  • 使用printf '%s\n' "$1"代替echo "$1"可以避免the POSIX definition of echo中的含糊不清(特别参见“应用程序使用”部分)。
  • 传递_的明确参数填入argv[0]广告位(又名$0)。

请注意,在很多情况下调用序列而不是字符串也会阻止您在所有中使用shell Seq("hello", "world").!不需要调用任何shell,但是可以实现以便直接启动名为hello的可执行文件,而"hello world".!等同于Seq("sh", "-c", "hello world").!,并且具有额外的可执行调用,其具有实现所需的性能成本和潜在的安全漏洞。有关(现在接近普遍修补)的情况的示例,请参阅Shellshock,其中没有明确的用户控制参数的shell调用在实践中仍然可能容易受到攻击(当从Web服务器调用以后的CGI约定用于导出时请求参数作为环境变量);因此,在可行的情况下避免不必要的壳是优选的行为。