語法分析 - 后臺(tái)運(yùn)行、管道、重定向
--- 后臺(tái)運(yùn)行
我們從上一節(jié)提到的入口點(diǎn) 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
;
這幾句語法的功能,就是平時(shí)很常用的:
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 對(duì)應(yīng)的符號(hào)是 '!'
這里把 BANG 和 pipeline 放到一起并不是說明 '!' 和管道有什么關(guān)系。
只是在這里實(shí)現(xiàn) '!' 這個(gè)符號(hào)的功能而已。
--- command_connect()
我們注意到,在語法的處理函數(shù)中,command_connect 這個(gè)函數(shù)被經(jīng)常使用。
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));
}
這個(gè)函數(shù)的作用就是把兩個(gè)相關(guān)的語法樹節(jié)點(diǎn)連接起來,并構(gòu)成一個(gè)新的節(jié)點(diǎn)。
而 COMMAND 這個(gè)數(shù)據(jù)結(jié)構(gòu),里面就包含了指向兩個(gè)孩子的指針,以及跟連接相關(guān)的屬性。
這里我們先不去詳細(xì)的看它。
--- 重定向
從 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
;
這個(gè)項(xiàng)應(yīng)該就是傳說中的,單項(xiàng)命令的實(shí)體了。
我們暫時(shí)不去理會(huì)其他的東西,先看一看 redirection_list。
那一段處理函數(shù)可以看出,它把一系列的重定向操作加入到 shell_command 的 redirects 鏈表尾部。
而 redirection_list 包含的內(nèi)容就比較多了,也就是重定向的所有語法啦。
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
;
可見,真的是十分之多阿,每一條后面我都加了注釋。
平時(shí)常用的基本只有幾種了,有一部分是《bash高級(jí)編程》里面提到的,
有些就是根本沒提到,完全沒見過的用法。。
現(xiàn)在我們先不去深究這些用法。