详解Unix/Linux中Shell脚本的输入输出 .

  Shell的I/O语法比较复杂,难以理解,更难以正确使用。Shell的输入输出语法有两个难点:重定向和文件描述符。我以前对Shell脚本输入/输出的理解也有错误。最近重新整理思路,决定写一篇文章来总结I/O重定向。


一、先介绍几个基本概念:

(1)文件(File):在Unix/Linux中,文件类型有七种,这七种类型是:目录、符号链接(指向另一个文件)、套接字文件、块设备文件、字符设备文件、命名管道文件、普通文件。这意味着,I/O设备被Unix/Linux视为“特殊”的文件,所以对设备进行输入输出等同于读写文件。

(2)文件描述符(File Descriptor ):实际上,Shell中的文件描述符等同于C语言中的文件结构(参见《The C Programming Languag》的7.5节),它是一个包含文件信息的结构,这些信息包括:缓冲区的位置,缓冲区中当前字符的位置,文件是否到达末尾等。Shell脚本通过文件描述符来读写文件。一个Shell脚本有10个文件描述符。其中,0、1、2是标准输入、标准输出和标准错误,我们可以任意使用的文件描述符是3 到9。

(3)重定向(Redirect):在Shell中,我们可以对命令(命令就是程序或脚本)的标准输入、标准输出和标准错误进行重定向,使其指向其他文件。

(4)重定向的作用域(Redirect's Scope ):重定向的“作用域”这个概念是我自己提出的,它对理解重定向的作用效果非常重要!我们来看下面这几个例子:

例1:重定向的“作用域”局限于一个命令
#!/bin/bash
echo "hello world"  > result.txt
解析:这个重定向的作用域是echo命令,命令结束重定向也就结束了。

例2:重定向的“作用域”局限于一个循环
#!/bin/bash
while read line
do
    echo "$line"
done < name.txt
解析:这个重定向的作用域是while循环,在循环执行期间,标准输入都被重定向到了当前目录的的name.txt文件,即每次read都是从文件中读取一行,且read是顺序读取文件的所有行。

while循环结束时,重定向就结束了。
#!/bin/bash
while read line < name.txt
do
    echo "$line"
done
解析:这个重定向的作用域是read命令,每次read都重新进行一次重定向。这造成了可怕的结果,每次都读取文件中的第一行,无限循环下去。


例3:重定向的“作用域”局限于整个脚本
#!/bin/bash
#This script called ltx_test
while read line
do
    echo "$line"
done

在终端运行这个脚本,执行命令
ltx_test < name.txt
解析:这个重定向的作用域是整个脚本,在脚本执行期间,标准输入都被重定向到了当前目录的的name.txt文件,即每次read都是从文件中读取一行,且read是顺序读取每一行。脚本结束时,重定向就结束了。



二、下面开始讨论Shell脚本中输入/输出的的两种情况:

(1)脚本只使用标准输入、标准输出和标准错误

    Shell会自动为我们打开和关闭0、1、2这三个文件描述符,我们不需要显式地打开或关闭它们。标准输入是命令的输入,默认指向键盘;标准输出是命令的输出,默认指向屏幕;标准错误是命令错误信息的输出,默认指向屏幕。

    如果没有显式地进行重定向,命令通过文件描述符0从屏幕读取输入,通过文件描述符1和2将输出和错误信息输出到屏幕。但如果我们想从其他文件(再次强调,I/O设备在Unix/Linux中也是文件)读取输入或产生输出,就需要对0、1、2使用重定向了。其语法如下:


command < filename                         把标准输入重定向到filename文件中
command 0< filename                       把标准输入重定向到filename文件中

command > filename                         把标准输出重定向到filename文件中(覆盖)
command 1> fielname                       把标准输出重定向到filename文件中(覆盖)

command >> filename                       把标准输出重定向到filename文件中(追加)
command 1>> filename                     把标准输出重定向到filename文件中(追加)

command 2> filename                       把标准错误重定向到filename文件中(覆盖)
command 2>> filename                     把标准输出重定向到filename文件中(追加)

command > filename 2>&1               把标准输出和标准错误一起重定向到filename文件中(覆盖)
command >> filename 2>&1             把标准输出和标准错误一起重定向到filename文件中(追加)

command < filename >filename2        把标准输入重定向到filename文件中,把标准输出重定向

                                                        到filename2文件中
command 0< filename 1> filename2   把标准输入重定向到filename文件中,把标准输出重定向

                                                        到filename2文件中

重定向的使用有如下规律:

1)标准输入0、输出1、错误2需要分别重定向,一个重定向只能改变它们中的一个。
2)标准输入0和标准输出1可以省略。(当其出现重定向符号左侧时)
3)文件描述符在重定向符号左侧时直接写即可,在右侧时前面加&。
4)文件描述符与重定向符号之间不能有空格!


(2)脚本使用外部文件

      当Shell脚本使用外部文件而不是默认的I/O设备作为输入输出时,我们“可以”使用3到9等几个文件描述符显式地打开或关闭外部文件。它的作用域是从显式打开文件到显式关闭文件之间。之所以说可以而不是必需,是因为我们可以重定向标准输入、输出和错误到外部文件来达到同样的目的。
      使用文件描述符显式打开文件需要使用内置命令exec,格式如下:
      exec  文件描述符(没有空格)重定向符号  文件
      使用文件描述符显式关闭文件,格式如下:
      exec  文件描述符(没有空格)<&-

例4:使用外部文件
#!/bin/bash
exec 3< name.txt
while read line <&3
do
    echo "$line"
done
exec 3<&-
解析:这个例子是从例2修改得来的,可以做比较。显式打开外部文件后,在循环执行期间,3都被重定向到了当前目录的的name.txt文件,即每次 read都是从文件中读取一行,且read是顺序读取文件的所有行。while循环结束时,重定向没有结束。直到显式文件为止。

在此声明,可以转载或引用,但必须注明出处,谢谢。      

 

源自:http://blog.csdn.net/ltx19860420/article/details/5561006

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值