Unix 的神秘之处就在于它的那些稀奇古怪的命令。比如在两个
斜杠之间是否需要加一个点,或者连字符后是否需要加引号。
要真正理解这些命令的话,就必须知道这些命令行是怎样被解释的。
Shell 程序(sh, ksh, csh, 或者其他变种) 读入并分析命令行,所以,命令行其实是对shell 程序的输入参数而已。
我们先来看一下读入的顺序:
1. 命令历史替换 (除了Bourne shell)
2. 分开单词,包括特殊字符
3. 更新命令历史(除了Bourne shell)
4. 解释单引号和双引号
5. 别名替换(除了Bourne shell)
6. 输入输出重定向 (< > 和 |)
7. 变量替换 (以 $开头的变量)
8. 命令替换 (命令s inside back quotes)
9. 文件名扩展 (file name wild cards)
你可以看到 Bourne shell 没有命令历史和别名替换的步骤,因为
Bourne shell 不包括这些功能。
1、命令历史替换
如果你在Korn shell (ksh), C shell (csh), 或者其他类似的 shell 设置了命令历史。
命令行就会在执行之前存入一个历史文件,你以后可以用
$ history
查看这些命令。
命令前面有一个数字:
13 ls *.txt
14 cd $HOME
15 ls *.log
在 Korn shell 里面,你可以用 r 加上数字来取回以前用过的命令。例如用r 13 就可以重复以上的 ls.$.txt 命令。
在C shell 里面,使用感叹号并且没有空格来替换r : !13。
处理命令行时,shell 首先检查命令替换,在历史文件里面寻找,取回每个命令,然后写入新的命令行。当然有关历史的处理不止简单的这些步骤。我们会在以后的文章中单独讨论。
2、分开单词
接下来的步骤就是把单词和特殊字符分开了。一个单词被shell 程序认为是命令的一部分。以下的命令用长格式列出当前目录并寻找包含mjb 的行。
ls -l|grep mjb
这个命令的单词包括:ls, -l, |, grep 以及mjb。单词也可以包含在引号里面。
在以下的命令中,一个长格式列表搜索创建于"Sep 07." 的文件。
ls -l|grep "Sep 07"
在这里,"Sep 07 " 作为一个单词被放入引号。
3、更新历史清单
一旦单词被确定,这个命令就写道历史文件的结尾。
4、 解释单引号和双引号
单引号里面的变量,不被处理,双引号里面的会被展开。
可以输入以下的命令来检验:
echo $PATH
echo $PATH
echo "$PATH"
第一行显示 $PATH 变量的值,第二行显示单词 $PATH,第三行显示 $PATH 变量的值。
5、别名替换
每个命令的第一个单词会和别名列表比较。下面的例子中,ls 和 grep 在别名清单中被检查,作别名替换。别名就是用一个命令来
替换另外一个命令的方法。例如:以下的命令:
alias ll ls -l
建立一个新的命令 ll,当你输入
ll *.txt
时,就像输入 ls -l *.txt 。
6、管道和重定向
到了这里,shell 程序“看”完了命令行里的所有单词。
对于 |, >, <, >>, 和其他的重定向命令,找到一个,就建立管道或者重定向。
7、变量扩展
现在命令行内的变量扩展,所有包含在双引号内的变量被替换成对应的值。
8、命令替换
命令替换查找反引号,执行括在其中的命令以及参数,然后使用运行结果作为参数传递给要执行的命令,例如:
ls -l `ls -p|grep /`|more
命令 ls -p 产生带给目录加注反斜杠的目录列表,如:
ls -p
STARTUP
file.txt
file2.txt
mystuff/
xdir/
加在后面的 grep / 命令只选择那些包含反斜杠的项:
ls -p|grep /
mystuff/
xdir/
把整个命令用反引号引进后,生成的结果作为参数传递给 ls -l
ls -l `ls -p|grep /`|more
这等同于:
ls -l mystuff/ xdir/|more
9、通配符
命令处理其寻找文件名的通配符并扩展他们。通配符包括:
* 和 ? 以及中括号,例如:
ls -l [abc]*
显示那些以 a 或 b 或 c 结尾的文件或者目录。
执行
最后命令被执行,这就完成了整个的流程。
需要指出的是:在上述第八步中,当处理反引号中的命令时,
先把它分离出来,作为一个单独的命令按照以上1-9步来处理,
对于用分号隔开的命令也一样。
jasonlv 于 2011-07-20 21:49:08发表:
1# CMK
支持
coolclever 于 2006-01-22 14:43:48发表:
恩.不错