Chinaunix首页 | 论坛 | 博客
  • 博客访问: 13816
  • 博文数量: 6
  • 博客积分: 130
  • 博客等级: 入伍新兵
  • 技术积分: 75
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-03 18:11
文章分类

全部博文(6)

文章存档

2012年(3)

2011年(3)

我的朋友

分类: LINUX

2012-01-02 12:52:32

大概了解了下bash的架子
那些内建命令什么的倒可以一点一点刨,倒是一些诸如“列出‘>/dev/null’文件的信息”之类的奇葩问题搞得我很是不爽
然后扒到了这么一段话,琢磨琢磨还是有好处的。

[Shell脚本学习指南]
[七.8 执行顺序与eval]

1. 将命令分割成token,是以固定的一组meta字符为分隔,有空格、制表字符、换行字符、;、(,)、<、>、|与&。token的种类包括单词(word)、关键字(keyword)、输出入重定向器,以及分号。

做了几个实验,大概能说明问题:
1) ls>/dev/null   # 正常执行
2) ls\>/dev/null  # ls>null: command not found 被转义的'>'不再是meta字符了
3) do        # syntax error near unexpected token `do'
4) \do       # do: command not found 大概可以这么理解:keyword实际上就是meta word,首字母被转义后也就作为普通word处理了,事实上第二条也给出了具体规则:

2. 检查每个命令的第一个token,看看是否它是不带有引号或反斜杠的关键字(keyword)。如果它是一个开放的关键字(if与其他控制结构的开始符号,如{或(),则这个命令其实是一个复合命令(compound command)。Shell为符合命令进行内部的设置,读取下一条命令,并再次启动进程。如果关键字非复合命令的开始符号(例如,它是控制结构的中间部分,像then、else或do,或是结尾部分,例如fi、done或逻辑运算符),则Shell会发出语法错误的信号。

也就是说,shell首先试图找"meta word",当然也可以通过转义或者引号来运行与之重名的命令;找到keyword但非法时,shell不会将其作为普通命令处理,而是直接给出错误信号。

3. 将每个命令的第一个单词与别名(alia)列表对照检查。如果匹配,它便代替别名的定义,并回到步骤1;否则,进行步骤4(别名是给交互式shell使用,因此我们在这里不谈)。回到步骤1,允许让关键字的别名被定义:例如alias aslongas=while 或者 alias procedure=function。注意,Shell不会执行递归(recursive)的别名展开:反而当别名展开为相同的命令时它会知道,并停止潜在的递归操作。可以通过引用要被保护的单词的任何部分而禁止别名展开。

实验:
alias hehe='a b c'
hehe # a: command not found 这样看来,的确是替换别名后返回步骤1重新分割token的
alias ll='ls -l'
alias ls=ll
aliass hehe=ll
hehe # ll: command not found Shell似乎是记录了所有出现过的命令,一旦发现重复就停止展开

到此为止,一切token分割工作都结束了

4. 如果波浪号(~)字符出现在单词的开头处,则将波浪号替换成用户的根目录($HOME)。将~user替换成user的根目录。波浪号替换(在支持此功能的Shell里)会发生在下面的位置:
a. 在命令行里,作为单词的第一个未引用字符
b. 在变量赋值中的 = 之后及变量赋值中的任何 : 之后
c. 形如${variable op word}的变量替换里的word部分

5. 将任何开头为$符号的表达式,执行参数(变量)替换。

6. 将任何形式为$(string)或`string`的表达式,执行命令替换。

7. 执行形如$((string))的算术表达式(arithmetic expression)

8. 从参数、命令与算术替换中取出结果行的部分,再一次将它们切分为单词。这次它使用$IFS里的字符作为定界符,而不是使用步骤1的那组meta字符。
通常,在IFS里连续多个重复的输入字符是作为单一定界符,这是你所期待的。这只有对空白字符(例如空格与制表字符)而言是真的。对于非空白字符,则不是这样的。举例来说,当读取以冒号分割字段的/etc/passwd文件时,两个连续冒号所定界的是一个空字段:
while IFS=: read name passwd uid gid fullname homedir Shell
do
   ...
done < /etc/passwd

还没有什么感觉 .. 等遇到问题再回来看看吧

9. 对于*、?,以及一对[...]的任何出现次数,都执行文件名生成(filename generation)的操作,也就是通配符展开。

实验证明,被转义或套引号的* ?是不会被展开的
同样没感觉 .. 再说吧

10. 使用第一个单词作为一个命令,遵循7.9节中所述的查找次序;也就是,先作为一个特殊的内建命令,接着做为函数,然后作为一般的内建命令,以及最后作为查找$PATH找到的第一个文件。

有关这一条,还是再补充一点比较好
man bash(1)

Command Execution

After a command has been split into words, if it results in a simple command and an optional list of arguments, the following actions are taken.

If the command name contains no slashes, the shell attempts to locate it. If there exists a shell function by that name, that function is invoked as described above in FUNCTIONS. If the name does not match a function, the shell searches for it in the list of shell builtins. If a match is found, that builtin is invoked.

If the name is neither a shell function nor a builtin, and contains no slashes, bash searches each element of the PATH for a directory containing an executable file by that name. Bash uses a hash table to remember the full pathnames of executable files (see hash under SHELL BUILTIN COMMANDS below). A full search of the directories in PATH is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell searches for a defined shell function named command_not_found_handle. If that function exists, it is invoked with the original command and the original command's arguments as its arguments, and the function's exit status becomes the exit status of the shell. If that function is not defined, the shell prints an error message and returns an exit status of 127.

If the search is successful, or if the command name contains one or more slashes, the shell executes the named program in a separate execution environment. Argument 0 is set to the name given, and the remaining arguments to the command are set to the arguments given, if any.

If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell script, a file containing shell commands. A subshell is spawned to execute it. This subshell reinitializes itself, so that the effect is as if a new shell had been invoked to handle the script, with the exception that the locations of commands remembered by the parent (see hash below under SHELL BUILTIN COMMANDS) are retained by the child.

If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the program. The shell executes the specified interpreter on operating systems that do not handle this executable format themselves. The arguments to the interpreter consist of a single optional argument following the interpreter name on the first line of the program, followed by the name of the program, followed by the command arguments, if any.

也就是说,$PATH只是为了方便而已,而已,... 莫蛋疼 ...

11. 在完成I/O重定向与其他同类事项之后,执行命令。
阅读(670) | 评论(0) | 转发(0) |
0

上一篇:nano - 普通篇

下一篇:dc计算器 - 语法篇

给主人留下些什么吧!~~