如何在 scala sys.process 调用上获得 shell 扩展
How to get shell expansion on scala sys.process invocations
考虑 shell 扩展的简单尝试:
Simple/direct方法:
scala> ("/bin/ls /tmp/*" run BasicIO(false, sb, None)).exitValue
ls: /tmp/*: No such file or directory
res18: Int = 1
我尝试了 ProcessIO、BasicIO、Process 等的多种组合,但无法弄清楚如何让 shell 扩展正常工作。
bash -c :
scala> ("bash -c \"/bin/ls /tmp/*\"" run BasicIO(false, sb, None)).exitValue
/tmp/*": -c: line 0: unexpected EOF while looking for matching `"'
/tmp/*": -c: line 1: syntax error: unexpected end of file
res19: Int = 2
管道到 bash -s :
scala> ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
<console>:1: error: ';' expected but ')' found.
("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
顺便说一下,shell 中的最后一个看起来像下面这样(并且有效):
21:28:32/dstat $echo "/bin/ls /tmp/*" | bash -s
/tmp/OSL_PIPE_501_SingleOfficeIPC_a974a3af70d46eaeed927022833718b7
/tmp/oobelib.log
/tmp/spark-steve-org.apache.spark.deploy.master.Master-1.pid
/tmp/spark-steve-org.apache.spark.deploy.worker.Worker-1.pid
/tmp/KSOutOfProcessFetcher.501.qQkpPp2uZLdVc5pukHmfJMR4bkM=:
Shell 转义也有助于理解 wrt scala Process 类:包含扩展和转义的示例将是最佳的。
UPDATE 我找到了这个 JIRA - 它可能是相关的。我希望不会 - 这意味着 little/no 希望此处描述的功能..
sys.process._ 可以接受的内容非常有限,无法使用 https://issues.scala-lang.org/browse/SI-7027
另一个更新 我发现了一个涉及尊敬的 Daniel Sobral 的旧电子邮件线程,他提到:
Because the quotes are not delimiting the parameter passed to bash --
it is Scala who decides how the arguments break up, and it simply
splits on spaces, without any quotation facility. If you try the
following, instead, it will work:
Seq("bash", "-c", "ls *.scala").!
"fire and forget" 版本的 运行 和 shell 命令看起来更加严峻。我向往ruby
%x{whatever shell string you want goes here}
例如
echo 'print %x{ls -lrtad /etc/* 2>&1}' | ruby
哪个最满意returns:
-r--r--r-- 1 root wheel 69836 May 28 2013 /etc/php.ini.default-
5.2-previous~orig
lrwxr-xr-x 1 root wheel 30 Oct 22 2013 /etc/localtime -> /usr/share/zoneinfo/US/Pacific
-rw-r--r-- 1 root wheel 102 Nov 5 2013 /etc/hostconfig
-rw-r--r-- 1 root wheel 1286 Nov 5 2013 /etc/my.cnf
-rw-r--r-- 1 root wheel 4161 Dec 18 2013 /etc/sshd_config~previous
-rw-r--r-- 1 root wheel 199 Feb 7 2014 /etc/shells
-rw-r--r-- 1 root wheel 0 Sep 9 2014 /etc/xtab
-rw-r--r-- 1 root wheel 1316 Sep 9 2014 /etc/ttys
.. etc
但看起来 Scala 没有发生..
恐怕您误会了我的回答。 Ruby 正在做同样的事情,我不用看他们的代码就知道这一点,因为 Java(以及扩展的 Scala)呈现为 API是直接翻译Unix的API.
shell 进行了 shell 扩展,虽然任何其他软件完全有可能模仿它们,但这将是一场失败的游戏.经常提供通配符,但它们只是 shell 扩展的一小部分。
我的回答包含您需要的一切,但让我进一步说明:
import scala.sys.process._
implicit class RubyX(val sc: StringContext) extends AnyVal {
def x(args: Any*): ProcessBuilder = {
val strings = sc.parts.iterator
val expressions = args.iterator
var buf = new StringBuffer(strings.next)
while(strings.hasNext) {
buf append expressions.next
buf append strings.next
}
Process(Seq("bash", "-c", buf.toString))
}
}
那你就可以了
x"ls *.scala".!
我返回了一个 ProcessBuilder,因此您可以选择最适合您的执行形式,例如 !
上面 returns 退出代码并将其他所有内容回显到标准输出。
考虑 shell 扩展的简单尝试:
Simple/direct方法:
scala> ("/bin/ls /tmp/*" run BasicIO(false, sb, None)).exitValue
ls: /tmp/*: No such file or directory
res18: Int = 1
我尝试了 ProcessIO、BasicIO、Process 等的多种组合,但无法弄清楚如何让 shell 扩展正常工作。
bash -c :
scala> ("bash -c \"/bin/ls /tmp/*\"" run BasicIO(false, sb, None)).exitValue
/tmp/*": -c: line 0: unexpected EOF while looking for matching `"'
/tmp/*": -c: line 1: syntax error: unexpected end of file
res19: Int = 2
管道到 bash -s :
scala> ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
<console>:1: error: ';' expected but ')' found.
("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
顺便说一下,shell 中的最后一个看起来像下面这样(并且有效):
21:28:32/dstat $echo "/bin/ls /tmp/*" | bash -s
/tmp/OSL_PIPE_501_SingleOfficeIPC_a974a3af70d46eaeed927022833718b7
/tmp/oobelib.log
/tmp/spark-steve-org.apache.spark.deploy.master.Master-1.pid
/tmp/spark-steve-org.apache.spark.deploy.worker.Worker-1.pid
/tmp/KSOutOfProcessFetcher.501.qQkpPp2uZLdVc5pukHmfJMR4bkM=:
Shell 转义也有助于理解 wrt scala Process 类:包含扩展和转义的示例将是最佳的。
UPDATE 我找到了这个 JIRA - 它可能是相关的。我希望不会 - 这意味着 little/no 希望此处描述的功能..
sys.process._ 可以接受的内容非常有限,无法使用 https://issues.scala-lang.org/browse/SI-7027
另一个更新 我发现了一个涉及尊敬的 Daniel Sobral 的旧电子邮件线程,他提到:
Because the quotes are not delimiting the parameter passed to bash -- it is Scala who decides how the arguments break up, and it simply splits on spaces, without any quotation facility. If you try the following, instead, it will work:
Seq("bash", "-c", "ls *.scala").!
"fire and forget" 版本的 运行 和 shell 命令看起来更加严峻。我向往ruby
%x{whatever shell string you want goes here}
例如
echo 'print %x{ls -lrtad /etc/* 2>&1}' | ruby
哪个最满意returns:
-r--r--r-- 1 root wheel 69836 May 28 2013 /etc/php.ini.default-
5.2-previous~orig
lrwxr-xr-x 1 root wheel 30 Oct 22 2013 /etc/localtime -> /usr/share/zoneinfo/US/Pacific
-rw-r--r-- 1 root wheel 102 Nov 5 2013 /etc/hostconfig
-rw-r--r-- 1 root wheel 1286 Nov 5 2013 /etc/my.cnf
-rw-r--r-- 1 root wheel 4161 Dec 18 2013 /etc/sshd_config~previous
-rw-r--r-- 1 root wheel 199 Feb 7 2014 /etc/shells
-rw-r--r-- 1 root wheel 0 Sep 9 2014 /etc/xtab
-rw-r--r-- 1 root wheel 1316 Sep 9 2014 /etc/ttys
.. etc
但看起来 Scala 没有发生..
恐怕您误会了我的回答。 Ruby 正在做同样的事情,我不用看他们的代码就知道这一点,因为 Java(以及扩展的 Scala)呈现为 API是直接翻译Unix的API.
shell 进行了 shell 扩展,虽然任何其他软件完全有可能模仿它们,但这将是一场失败的游戏.经常提供通配符,但它们只是 shell 扩展的一小部分。
我的回答包含您需要的一切,但让我进一步说明:
import scala.sys.process._
implicit class RubyX(val sc: StringContext) extends AnyVal {
def x(args: Any*): ProcessBuilder = {
val strings = sc.parts.iterator
val expressions = args.iterator
var buf = new StringBuffer(strings.next)
while(strings.hasNext) {
buf append expressions.next
buf append strings.next
}
Process(Seq("bash", "-c", buf.toString))
}
}
那你就可以了
x"ls *.scala".!
我返回了一个 ProcessBuilder,因此您可以选择最适合您的执行形式,例如 !
上面 returns 退出代码并将其他所有内容回显到标准输出。