一、Shell 输入/输出重定向
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
文件描述符(fd):文件描述符是一个非负整数,在打开现存文件或新建文件时,内核会返回一个文件描述符,读写文件也需要使用文件描述符来访问文件。
 内核为每个进程维护该进程打开的文件记录表。文件描述符只适于 Unix、Linux 操作系统。
文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

二、重定向符号
输入和输出可以被重定向符号解释到 shell。
 shell 命令是从左到右依次执行命令。
 >  符号左边输出作为右边输入(标准输出)
 >> 符号左边输出追加右边输入
 <  符号右边输出作为左边输入(标准输入)
 << 符号右边输出追加左边输入
 &  重定向绑定符号
1、重定向输出
 重定向一般通过在命令间插入特定的符号来实现。
 实例:
 执行下面的 who 命令,它将命令的完整的输出重定向在用户文件中(users):
 $ who > users
 执行后,并没有在终端输出信息,这是因为输出已被从默认的标准输出设备(终端)重定向到指定的文件。
 你可以使用 cat 命令查看文件内容:
 $ cat users
输出重定向会覆盖文件内容,请看下面的例子:
 $ echo "username is john" > users
 $ cat users
 username is john
如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾,例如:
$ echo "username is john" >> users
 $ cat users
 username is john
 username is john
  
2、重定向输入
 一般格式:[n]<word
 如果 n 没有指定,默认是 0
 示例:
 a.txt 内容作为 grep 输入:
 # grep "test" --color < a.txt
实例:
 接着以上实例,我们需要统计 users 文件的行数,执行以下命令:
$ wc -l users
        2 users
 也可以将输入重定向到 users 文件:
$  wc -l < users
        2  
  
三、重定向标准输出和标准错误
1)覆盖重定向标准输出和标准错误
 &>word 和>&word 等价于 >word 2>&1 
 &将标准输出和标准输入绑定到一起,重定向 word 文件。
 示例:
 当不确定执行对错时都覆盖到文件:
 # echo "1 + 1" |bc &> error.log
 当不确定执行对错时都覆盖到文件:
 # echo "1 + 1" |bc > error.log 2>&1
2)追加重定向标准输出和标准错误
 &>>word 等价于>>word 2>&1
 示例:
 当不确定执行对错时都追加文件:
 # echo "1 + 1" |bc &>> error.log
3)重定向操作符command << delimiter
 shell将分界符delimiter之后直至下一个同样的分界符之前的所有内容都作为输入,遇到下一个分界符,shell就知道输入结束了。
 这一命令对于自动或远程的例程非常有用。可以任意定义分界符delimiter,最常见的是EOF。
示例:自动登录ftp下载文件
 ftp -in 192.168.100.100 <<EOF
 user test test
 get 1.txt
 bye
 EOF
四、重定向到空设备
/dev/null 是一个空设备,向它写入的数组都会丢弃,但返回状态是成功的。与其对应的还有一个/dev/zero 设备,提供无限的 0 数据流。
 在写 Shell 脚本时我们经常会用到/dev/null 设备,将 stdout、stderr 输出给它,也就是我们不想要这些输出的数据。
 通过重定向到/dev/null 忽略输出,比如我们没有安装 bc 计算器,正常会抛出没有发现命令:
 # echo "1 + 1" |bc >/dev/null 2>&1
 这就让标准和错误输出到了空设备。
 忽略标准输出:
 # echo "test" >/dev/null
 忽略错误输出:
 # echo "1 + 1" |bc 2>/dev/null
  
五、read 命令
read 命令从标准输入读取,并把输入的内容复制给变量。
 命令格式: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p 
 prompt] [-t timeout] [-u fd] [name ...]

获取用户输入保存到变量:
 # read -p "Please input your name: " VAR
 Please input your name: lizhenliang
用户输入保存为数组:
 # read -p "Please input your name: " -a ARRAY
 Please input your name: a b c
 # echo ${ARRAY[*]}
 a b c
遇到 e 字符返回:
 # read -d e VAR
 123
 456
 e
 # echo $VAR
 123 456
  
从文件作为 read 标准输入: # cat a.txt adfasfd # read VAR < a.txt # echo $VAR adfasfd while 循环读取每一行作为 read 的标准输入: # cat a.txt |while read LINE; do echo $LINE; done 123 abc 分别变量赋值: # read a b c 1 2 3 # echo $a 1 # echo $b 2 # echo $c 3