我一直都不是命令行的大用户。有人甚至可以说我主动避免使用它!老天,我甚至没有用命令行参数编写过程序,因为它总是感觉有点像复活恐龙——我们都知道结果会怎样。
这种精心培养的无知在讨论如何改进 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
如果这一切对你都有意义,欢迎加入启蒙人士的行列!
我看起来更像是这样
显然,这一切都是经过深思熟虑的,而缺失的是正确的心理模型。
首先,请记住,总是有一个 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 添加了一种打印方式,使命令的数组性质更加清晰
加上一些文档改进,我认为这对像我这样的傻瓜来说也是可行的 :)