这是因为我们的 SHELL 尝试执行 ls -l
,但是并没有找到叫这个名字的程序。我们的意思是执行 ls
,带上 -l
的参数。当前,我们的程序还不支持接受命令参数。要修复这个问题,需要修改 execLine
函数,将要执行的命令以空格拆分。
func execInput(input string) error {
// Remove the newline character.
input = strings.TrimSuffix(input, "\n")
// Split the input to separate the command and the arguments.
args := strings.Split(input, " ")
// Pass the program and the arguments separately.
cmd := exec.Command(args[0], args[1:]...)
...
}
程序的名字现在存储在 args[0] 中,程序执行的参数存储在数组其他索引中。执行 ls -l
现在可以得到预期的结果。
> ls -l
total 24
-rw-r--r-- 1 simon staff 1076 30 Jun 09:49 LICENSE
-rw-r--r-- 1 simon staff 1058 30 Jun 10:10 main.go
-rw-r--r-- 1 simon staff 897 30 Jun 09:49 main_test.go
更改目录(cd)
现在,我们已经可以带着参数执行命令了。现有的这些功能,距离达到一个最小的可用性,只差了一点点。你也许在使用我们的 Shell 时候,已经注意到了:你无法通过 cd
改变当前命令执行的目录。
> cd /
> ls
LICENSE
main.go
main_test.go
不,这不是我们根目录的内容。那为什么 cd
命令不起作用呢?要理解这点很容易:没有真正的 cd
程序,该功能是 SHELL
的内置命令。
我们必须对 execInput
函数再次进行修改。在 Split
方法后面,我们添加 switch
结构语句,并将 args[0] 作为它的参数。当这个命令是 cd
,我们检查它后面是否还有参数,如果没有指定参数,我们无法改变当前目录(在大多数 SHELL 中,不指定参数,将跳转到主目录)。当 args[1]
中有一个后续参数时(存储路径的参数),我们使用 os.Chdir(args[1])
更改目录。在 case
块的末尾,我们返回 execInput
函数以停止其他处理。
因为如此简单,我们在 cd
块后面,再添加一个 exit
命令,exit 可以用来退出当前SHELL(另一个退出方法是 CTRL+C
)。
// Split the input to separate the command and the arguments.
args := strings.Split(input, " ")
// Check for built-in commands.
switch args[0] {
case "cd":
// 'cd' to home dir with empty path not yet supported.
if len(args) < 2 {
return errors.New("path required")
}
// Change the directory and return the error.
return os.Chdir(args[1])
case "exit":
os.Exit(0)
}
...
可以看到,此时输出的内容,相较于之前的输出结果,更像是我们的根目录。
> cd /
> ls
Applications
Library
Network
System
...
至此,我们已经完成了这个简单的 SHEEL 的编写。
考虑改善的地方
此时,如果你觉得有些无聊,你可以尝试改进这个 SHELL。下面是一些可以改善的点:
修改光标所在行的显示:
- 增加当前目录
- 增加机器名称
- 增加当前用户
- 通过输入 up/down 键,来翻阅输入的历史
结尾
至此,本文已接近尾声,我希望你读的愉快。如你所见,SHELL 背后的概念十分简单。
Go 同样是一门十分简单的编程语言,它帮助我们更快的得到想要的结果。我们无需关心内存管理。Rob Pike 和 Ken Thompson,以及 Robert Griesemer 共同创造了 Go,他们也创造了 Unix,所以,使用 Go 编写 SHELL 是个很好的选择。
我也一直在学习,如果你发现本文有哪些可改进的地方,请联系我。
本文来自:Segmentfault
感谢作者:shiweifu
查看原文:[译] 使用 Go 语言编写一个简单的 SHELL
相关阅读 >>
更多相关阅读请进入《Go》频道 >>
Go语言101
一个与时俱进的Go编程知识库。