语法分析 - 后台运行、管道、重定向
--- 后台运行
我们从上一节提到的入口点 inputunit 看起。
inputunit: simple_list simple_list_terminator
...
;
simple_list: simple_list1
| simple_list1 '&'
| simple_list1 ';'
;
simple_list1: simple_list1 AND_AND newline_list simple_list1
| simple_list1 OR_OR newline_list simple_list1
| simple_list1 '&' simple_list1
| simple_list1 ';' simple_list1
| pipeline_command
;
这几句语法的功能,就是平时很常用的:
check_ok && do_sth
file_exists || create_it
firefox &
do_a; do_b; do_c; do_d
--- 管道
来看一下 pipe_command
pipeline_command: pipeline
| BANG pipeline
...
;
pipeline:
pipeline '|' newline_list pipeline
| command
;
newline_list:
| newline_list '\n'
;
BANG 对应的符号是 '!'
这里把 BANG 和 pipeline 放到一起并不是说明 '!' 和管道有什么关系。
只是在这里实现 '!' 这个符号的功能而已。
--- command_connect()
我们注意到,在语法的处理函数中,command_connect 这个函数被经常使用。
COMMAND *
command_connect (com1, com2, connector)
COMMAND *com1, *com2;
int connector;
{
CONNECTION *temp;
temp = (CONNECTION *)xmalloc (sizeof (CONNECTION));
temp->connector = connector;
temp->first = com1;
temp->second = com2;
return (make_command (cm_connection, (SIMPLE_COM *)temp));
}
这个函数的作用就是把两个相关的语法树节点连接起来,并构成一个新的节点。
而 COMMAND 这个数据结构,里面就包含了指向两个孩子的指针,以及跟连接相关的属性。
这里我们先不去详细的看它。
--- 重定向
从 pipeline 引出了 command 。
command: simple_command
| shell_command
| shell_command redirection_list
{
COMMAND *tc;
tc = $1;
if (tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = $2;
}
else
tc->redirects = $2;
$$ = $1;
}
| function_def
;
redirection_list: redirection
| redirection_list redirection
;
这个项应该就是传说中的,单项命令的实体了。
我们暂时不去理会其他的东西,先看一看 redirection_list。
那一段处理函数可以看出,它把一系列的重定向操作加入到 shell_command 的 redirects 链表尾部。
而 redirection_list 包含的内容就比较多了,也就是重定向的所有语法啦。
redirection: '>' WORD // > xxx
| '<' WORD // < xxx
| NUMBER '>' WORD // 1> xxx
| NUMBER '<' WORD // 0< xxx
| GREATER_GREATER WORD // >> xxx
| NUMBER GREATER_GREATER WORD // 2>> xxx
| LESS_LESS WORD // << xxx
| NUMBER LESS_LESS WORD // 0<< xxx
| LESS_LESS_LESS WORD // <<< xxx
| NUMBER LESS_LESS_LESS WORD // 0<<< xxx
| LESS_AND NUMBER // <&2
| NUMBER LESS_AND NUMBER // 1<&2
| GREATER_AND NUMBER // >&1
| NUMBER GREATER_AND NUMBER // 2>&1
| LESS_AND WORD // <& xxx
| NUMBER LESS_AND WORD // 1<& xxx
| GREATER_AND WORD // >& xxx
| NUMBER GREATER_AND WORD // 1>& xxx
| LESS_LESS_MINUS WORD // <<- xxx
| NUMBER LESS_LESS_MINUS WORD // 1 <<- xxx
| GREATER_AND '-' // >&-
| NUMBER GREATER_AND '-' // 1>&-
| LESS_AND '-' // <&-
| NUMBER LESS_AND '-' // 1<&-
| AND_GREATER WORD // &> xxx
| NUMBER LESS_GREATER WORD // 1<> xxx
| LESS_GREATER WORD // <> xxx
| GREATER_BAR WORD // >| xxx
| NUMBER GREATER_BAR WORD // 1>| xxx
;
可见,真的是十分之多阿,每一条后面我都加了注释。
平时常用的基本只有几种了,有一部分是《bash高级编程》里面提到的,
有些就是根本没提到,完全没见过的用法。。
现在我们先不去深究这些用法。