命令插值傻瓜教程

2017 年 10 月 5 日 | 😄

我一直都不是命令行的大用户。有人甚至可以说我主动避免使用它!老天,我甚至没有用命令行参数编写过程序,因为它总是感觉有点像复活恐龙——我们都知道结果会怎样。

这种精心培养的无知在讨论如何改进 Julia shell 接口的学习曲线时派上了用场。

事实证明,它是由在命令行上出生的人设计的,对于像我这样的人来说,使用起来很混乱。现在我了解了事情的运作方式,我想分享我新获得的知识!

让我们从基础和我的第一个心理模型开始。你可以像这样运行一个命令

julia> run(`julia -e 'println("hello world")'`);
hello world

由于这看起来与我在终端中输入的一模一样,我推断这是通用规则:只要让它看起来像一个命令,它就会像一个命令一样运行!

但当我们开始在命令中插值时,这就会崩溃。让我们考虑以下内容

julia> flag1 = "-e 'println(\"hello world\")'";

julia> flag2 = "println(\"hello world\")";

julia> helloworld = "hello world";

julia> `julia $flag1`
`julia "-e 'println(\"hello world\")'"` # okay?! Guess strings get quotes

julia>` julia -e 'println($helloworld)'`
`julia -e 'println($helloworld)'` #what?

julia> `julia -e $flag2`
`julia -e 'println("hello world")'` # WHAT? Where are my "

julia> a = "some   thing";

julia> b = `some   thing`;

julia> run(`echo $a`);
some   thing

julia> run(`echo $b`);
some thing

如果这一切对你都有意义,欢迎加入启蒙人士的行列!

我看起来更像是这样

image

显然,这一切都是经过深思熟虑的,而缺失的是正确的心理模型。

首先,请记住,总是有一个 main 坐在某个地方,耐心地等待你向它提供一个字符串数组。

传统的 main(int argc, char** argv)

现在,shell 所做的是通过空格将我们输入的单个命令字符串分割,以便将其传递给这个 main。然后,它显然需要一种方法来创建一个带有空格的字符串,这就是 '...'"..." 发挥作用的地方。如果我理解正确的话,所有其他字符都只是约定俗成的。因此 -e 中的减号不会被特殊对待,正如我之前假设的那样。因此,-e'println("hello world")' 只是在语义上属于一起,但在构建字符串数组时并不属于一起。因此,尝试将 '-e''...' 块一起插值会惨败,因为 Julia 会尝试将其解释为一个字符串。导致我未能找到正确解决方案的原因是,Julia 实际上比 shell 更强大,因为我们可以直接将一个字符串数组传递给命令。因此,这实际上有效

run(Cmd(["julia", "-e", "println(\"hello world\")"]))

请注意,以上等同于

run(`julia $(["-e", """println("hello world")"""])`)

因此,我们实际上可以进行更好的插值,因为我们只需要将一个新的字符串插入数组。

这就是为什么这实际上有效

julia -e $("println(\"hello world\"))

只需省略任何 '...',让 Julia 将其转换为具有正确转义字符串的命令。

现在,在 Julia 0.7 中,Keno Fischer 添加了一种打印方式,使命令的数组性质更加清晰

image

加上一些文档改进,我认为这对像我这样的傻瓜来说也是可行的 :)