語法分析 - 后臺運行、管道、重定向
--- 后臺運行
我們從上一節提到的入口點 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高級編程》里面提到的,
有些就是根本沒提到,完全沒見過的用法。。
現在我們先不去深究這些用法。