Shell 输入/输出重定
Linux系统命令从你的终端接受输入并将所产生的输出发送回到终端。默认情况下标准输入输出就是终端输入一条命令然后输出一些信息。
标准输入输出是在终端上完成的,但是如果要重定向到某个文件或者别的输入输出管道就需要用到输入输出重定向。
重定向表:
输出重定向
hadoop@liutao-GE5S:~/shell$ ls
storm-config.sh storm-startall.sh zk-config.sh zk-stopall.sh
storm-jps.sh storm-stopall.sh zk-startall.sh
hadoop@liutao-GE5S:~/shell$ ls > ./file // > 代表的覆盖,>>代表追加到文件最后
hadoop@liutao-GE5S:~/shell$ ls
file storm-jps.sh storm-stopall.sh zk-startall.sh
storm-config.sh storm-startall.sh zk-config.sh zk-stopall.sh
hadoop@liutao-GE5S:~/shell$ cat file
file
storm-config.sh
storm-jps.sh
storm-startall.sh
storm-stopall.sh
zk-config.sh
zk-startall.sh
zk-stopall.sh
输入重定向
和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:
command1 < file1
案例:
hadoop@liutao-GE5S:~/shell$ cat file
aaaaa
hadoop@liutao-GE5S:~/shell$ read -p "输入:" param < ./file
hadoop@liutao-GE5S:~/shell$ echo $param
aaaaa
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
command > /dev/null 2>&1
重定向深入讲解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
标准输出文件(stdout):stdout的文件描述符为1,Unix程序默认向stdout输出数据。
标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。 默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
command>/dev/null
其实这条命令是一个缩写版,对于一个重定向命令,肯定是 a > b 这种形式
那么command > /dev/null 难道是command充当a的角色,/dev/null充当b的角色。
这样看起来比较合理,其实一条命令肯定是充当不了a,肯定是command执行产生的输出来充当a,其实就是标准输出stdout。
所以 command > /dev/null 相当于执行了 command 1>/dev/null 。执行command产生了标准输出stdout(用1表示),重定向到/dev/null的设备文件中。
command 1>/dev/null中1后面不要有空格
2>&1
通过上面 command > /dev/null 等价于 command 1 > /dev/null ,那么对于 2>&1也就好理解了,2就是标准错误,1是标准输出,那么这条命令不就是相当于把标准错误重定向到标准输出么。
是&1而不是1,这里&是什么?这里 & 相当于 等效于标准输出 。这里有点不好理解。
command>a 2>a 与 command>a 2>&1的区别
通过上面的分析,对于 command>a 2>&1 这条命令,等价于 command 1>a 2>&1 可以理解为执行command产生的标准输入重定向到文件a中,标准错误也重定向到文件a中。那么是否就说 command 1>a 2>&1 等价于 command 1>a 2>a 呢。其实不是, command 1>a 2>&1 与 command 1>a 2>a 还是有区别的,区别就在于前者只打开一次文件a,后者会打开文件两次,并导致stdout被stderr覆盖。 &1 的含义就可以理解为用标准输出的引用,引用的就是重定向标准输出产生打开的a。从IO效率上来讲, command 1>a 2>&1 比 command 1>a 2>a 的效率更高。
Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。开始的delimiter前后的空格会被忽略掉。
使用cat <<EOF来输入多行数据到文件中
cat(英文全拼:concatenate)命令用于连接文件并打印到标准输出设备上。
当需要将多行数据输入到文本时,如果每条都使用echo 到文件时是比较繁琐的,这种情况下可以使用cat EOF进行多行文件的覆盖或追加输入。
一、覆盖
这里有两种格式可以使用
1、格式一
#!/bin/bash
cat << EOF > /root/test.txt
Hello!
My site is www.361way.com
My site is www.91it.org
Test for cat and EOF!
EOF
2、格式二
#!/bin/bash
cat > /root/test.txt <<EOF
Hello!
My site is www.361way.com
My site is www.91it.org
Test for cat and EOF!
EOF
两种写法区别无法是要写入的文件放在中间或最后的问题,至于选哪种看个人喜好吧。
二、追加
覆盖的写法基本和追加一样,不同的是单重定向号变成双重定向号。
1、格式一
#!/bin/bash
cat << EOF >> /root/test.txt
Hello!
My site is www.361way.com
My site is www.91it.org
Test for cat and EOF!
EOF
2、格式二
#!/bin/bash
cat >> /root/test.txt <<EOF
Hello!
My site is www.361way.com
My site is www.91it.org
Test for cat and EOF!
EOF
需要注意的是,不论是覆盖还是追加,在涉及到变量操作时是需要进行转义的,例如:
#!/bin/bash
cat <<EOF >> /root/a.txt
PATH=\$PATH:\$HOME/bin
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=\$ORACLE_BASE/10.2.0/db_1
export ORACLE_SID=yqpt
export PATH=\$PATH:\$ORACLE_HOME/bin
export NLS_LANG="AMERICAN_AMERICA.AL32UTF8"
EOF
Shell 文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
案例
创建两个 shell 脚本文件。
test1.sh 代码如下:
#!/bin/bash
url="http://www.runoob.com"
echo "asaaa"
test2.sh 代码如下:
#!/bin/bash
. ./test1.sh
echo "$url"
# 或者使用以下包含文件代码
# source ./test1.sh
接下来,我们为 test2.sh 添加可执行权限并执行:
chmod +x test2.sh
./test2.sh
http://www.runoob.com
echo "asaaa"
注:被包含的文件 test1.sh 不需要可执行权限。