编写自己的Shell解释器-2[转]

Shell语法梗概

我们不停的命令 bash 做这做那,一般情况下它都很听话,按你的吩咐去做。可有时候,它会对你说:“嗨,老兄,你的命令我理解不了,无法执行”。例如,你输入这样的命令:

[root@stevesn root]# aaaaaa

 

bash会告诉你:

bash: aaaaaa: command not found

 

是的,你必须说的让它能听懂,否则它就给你这么一句抱怨,当然也还会有其它的牢骚。

那么,什么样格式的命令,它才能正确理解执行了?这就要引出shell 的语言规范了。

Shell作为一个命令语言解释器,有一套自己的语言规范,凡是符合这个规范的命令,它就可以正确执行,否则就会报错。这个语言规范是在 IEEE POSIX的第二部分:“shelltools规范”中定义的。关于这份规范,可以在这里看到。

官方的东西,总是冗长而且晦涩,因为它要做到面面俱到且不能有破绽。如果读者有兴趣,可以仔细研究这份规范。而我们的目的只是理解shell的实现思想,然后去实现一个简单的 shell 解释器,所以没必要陷入枯燥的概念之中。

现在请继续在 linux 字符界面下输入 man bash,调出 bash 的帮助页面,然后找到 shell语法”那一部分,我们就是以这里的描述作为实现的依据。

bash帮助的“shell 语法”一节,是这样来定义shell 语法的:

l         简单命令

简单命令是(可选的)一系列变量赋值, 紧接着是空白字符分隔的词和重定向符号, 最后以一个控制操作符结束. 第一个词指明了要执行的命令, 它被作为第 0 个参数. 其余词被作为这个命令的参数.

       这个定义可以这样来理解:

1、  可以有变量赋值,例如

a=10 b=20 export a b

2、  “词”是以空白字符分隔开的,空白字符包括制表符(tab)和空格,例如:

ls /tmp

就是两个词,一个 ls,一个 /tmp

3、可以出现重定向符号,重定向符号是“>”和“<”,例如:

echo “hello world” > /tmp/log

4、  简单命令结束于控制操作符,控制操作符包括:

||  &   &&     ;   ;;  ( )   |  <newline>

例如,用户输入:

ls /tmp

用户最后敲的回车键就是控制操作符 newline,表示要结束这个简单命令。

如果用户输入:

echo “100” ; echo “200”

那么这是两个简单命令,第一个结束于“;”,第二个结束于newline

5、  简单命令的第一个词是要执行的命令,其余的词都是这个命令的参数,例如:

echo “hello world” echo

第一个echo 是命令,第二个词“hello world”是参数1,第三个词 echo 是参数2,而不再作为一个命令了。

简单命令是 shell 语法中最小的命令,通过简单命令的组合,又可以得到管道命令和列表命令。

l         管道(命令)

管道是一个或多个简单命令的序列,两个简单命令之间通过管道符号(“|”)来分隔

例如

echo “hello world” | wc –l

就是一个管道,它由两个简单命令组成,两个简单命令之间用管道符号分隔开。

我们可以看到,管道符号“|”也是属于上面提到的控制操作符。

根据这个定义,一个简单命令也同时是一个管道。

管道的作用是把它前面的那个简单命令的输出作为后面那个简单命令的输入,就上面这个例子来说:

echo “hello world” 本来是要在标准输出(屏幕)上打印 “hello world” 的,但是管道现在不让结果输出到屏幕上,而是“流”到 wc –l 这个简单命令,wc –l 就把“流”过来的数据作为它的标准输入进行计算,从而统计出结果是 1 行。

关于管道更详细的内容,我们在后面具体实现管道的时候再说明。

l         列表(命令):

列表是一个或多个管道组成的序列,两个管道之间用操作符 ;, &, &&, || 分隔。我们看到,这几个操作符都属于控制操作符。

例如

echo “hello world” | wc –l ; echo “nice to meet you”

就是一个列表,它由两个管道组成,管道之间用分号(;)隔开

分号这种控制操作符仅仅表示一种执行上的先后顺序。

l         复合命令

       这个定义比较复杂,实现起来也有相当难度,在咱们这个示例程序中,就不实现了。

以上是 shell 语法规范的定义,我们的 shell 程序就是要以此规范为依据,实现对简单命令、管道和列表的解释。对于列表中的控制操作符,我们只支持分号(;),其它的留给读者自己来实现。

       接下来,我们具体介绍如何实现一个简单的 shell解释器。

posted @ 2008-12-05 21:29  aoogur  阅读(473)  评论(0编辑  收藏  举报