注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

bash中重定向操作的优先级  

2012-08-13 00:31:00|  分类: bash分析 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、重定向
文件是unix的重要概念,而脚本中对于文件的操作则主要是通过文件中定向来实现的。文件的重定向对于bash来说比较重要,也相对比较复杂,加上和各种命令以及运算符的结合,它的模糊性可能还会增加,这里通过bash的语法文件来大致描述一下bash中重定向的优先级及使用方法。
二、重定向的使用
pipeline:    pipeline '|' newline_list pipeline  这里说明一个重要问题,pipe命令的优先级是最低的,要低于重定向操作,所以文件重定向只对管道两侧的命令单独生效
            { $$ = command_connect ($1, $4, '|'); }
    |    pipeline BAR_AND newline_list pipeline
            {
              /* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */
  ……
            }
    |    command
            { $$ = $1; }
command:    simple_command
            { $$ = clean_simple_command ($1); }
    |    shell_command
            { $$ = $1; }
    |    shell_command redirection_list shell command包含了shell定义的命令,例如while、for、if等结构控制命令同样可以看到,shell命令的重定向优先级高于pipe,但是小于简单基本命令中重定向优先级
            {
     ……
            }
    |    function_def
            { $$ = $1; }
    |    coproc
            { $$ = $1; }
    ;
simple_command:    simple_command_element
            { $$ = make_simple_command ($1, (COMMAND *)NULL); }
    |    simple_command simple_command_element
            { $$ = make_simple_command ($2, $1); }
    ;
simple_command_element: WORD  单纯的一个单词,最为平凡的语法单位
            { $$.word = $1; $$.redirect = 0; }
    |    ASSIGNMENT_WORD  简单来说,是一个中间包含了‘=’的单词,它的特点在于它不是shell的关键字,但是需要shell来执行这个操作
            { $$.word = $1; $$.redirect = 0; }
    |    redirection 这个比较丰富多彩,包括了各种文件的重定向,由于它语法定义比较多,这里不再展开
            { $$.redirect = $1; $$.word = 0; }
    ;
三、一个命令字符串的组成和拼凑
一般来说命令都是有顺序的,例如
print hello world
如果顺序颠倒,那结果一定错误,我们看一下bash中对于命令字符串的拼凑:

simple_command:    simple_command_element
            { $$ = make_simple_command ($1, (COMMAND *)NULL); }
    |    simple_command simple_command_element
            { $$ = make_simple_command ($2, $1); }
    ;
simple_command_element: WORD
            { $$.word = $1; $$.redirect = 0; }
    |    ASSIGNMENT_WORD
            { $$.word = $1; $$.redirect = 0; }
    |    redirection
            { $$.redirect = $1; $$.word = 0; }
    ;
基本的命令元素包含了单词、赋值单词和重定向三种,它们统称为simple_command_element,然后它们组成simple_command,一个simple_command的组成包括了

simple_command:    simple_command_element
            { $$ = make_simple_command ($1, (COMMAND *)NULL); }
    |    simple_command simple_command_element
            { $$ = make_simple_command ($2, $1); }
    ;

print hello world
为例,它的第一个print将会首先被识别为simple_command_element,然后进一步规约为一个simple_command,也就是使用了simple_command的第一个生成式,所以第一个元素经过了两次归于命令,第二次就是make_simple_command,此时是真正创建了一个命令,并且print作为了该命令的开始;相反,对于之后的 hello ,它规约为simple_command使用的是第二个生成式,此时越过了第一个生成式的创建,而是通过第二个将新的字符串追加到了print引导的命令,这就是先下手为强的道理。
四、文件中单词的分隔
一个cat出来的文件可能会包含很多的换行,这些换行的处理是由shell统一完成的,执行的路径为
(gdb) bt
#0  word_list_split (list=0x8128228) at subst.c:8468
#1  0x0809905c in shell_expand_word_list (tlist=0x8128128, eflags=31)
    at subst.c:8917
#2  0x08099239 in expand_word_list_internal (list=0x8126968, eflags=31)
    at subst.c:9010
#3  0x080989e5 in expand_words (list=0x8126968) at subst.c:8632
#4  0x0807772b in execute_simple_command (simple_command=0x8126948,
    pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x81269a8)
    at execute_cmd.c:3645
#5  0x08072a5e in execute_command_internal (command=0x8126ae8, asynchronous=0,
    pipe_in=-1, pipe_out=-1, fds_to_close=0x81269a8) at execute_cmd.c:730
#6  0x0807227a in execute_command (command=0x8126ae8) at execute_cmd.c:375
#7  0x080609ea in reader_loop () at eval.c:152
#8  0x0805ea89 in main (argc=2, argv=0xbffff3c4, env=0xbffff3d0) at shell.c:749
(gdb) p ifs_value
$12 = 0x8122128 " \t\n"
(gdb)
其中代码基于bash-4.1版本调试。
  评论这张
 
阅读(772)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017