IO重定向与管道
一、三种IO设备
程序:数据+指令 或 数据结构+算法
程序必须能够读入输入然后经过加工来产生结果,其接受的输入可以是变量、数组、列表、文件等等,生产出来的结果可以使变量、数组、列表、文件等等。即:
程序都有读入数据和输出数据的需求
读入数据:input	
输出数据:output
Linux给程序提供三种IO设备:
- 标准输入(STDIN)-0 默认接受来自键盘的输入
- 标准输出(STDOUT)-1 默认输出到终端窗口
- 标准错误(STDERR)-2 默认输出到终端窗口
在Linux中,一切皆文件,我们没打开文件,系统都会自动分配一个FD(file description,文件描述符)。上面的0,1,2就是系统分配的文件描述符。
ll /proc/$$/fd    查看目前的文件描述符
exec 8<>/data/hosts    
表示给/data/hosts文件指定一个文件描述符8,且8与/data/hosts之间是软链接
exec 8>&-    删除8号这个文件描述符

二、IO重定向:改变默认位置
- 
>标准的输出重定向:
 ls > /dev/pts/5命令ls重定向输出至窗口5
 ls > /data/ls.out命令ls重定向输出至/data/ls.out文件中
 注意:假如ls.out文件中本来就有内容,那么重定向输出后会覆盖文件中原有的内容
- 
>>:追加重定向,新内容会追加至目标文件尾部
 ls >> /data/ls.out
- 
():合并多个程序的STDOUT 
 (cal 2007;cal 2008) > all.txt
2>标准错误的输出重定向:
cmd  2>  /data/err.log      cmd(本身无cmd这个命令,所以输入此命令会显示错误的结果)的错误结果重新定向显示至 data/err.log  中
注意:history 2> /data/err.log  由于本身history命令是正确的,所以默认的输出设备会正常显示history命令的内容,且不会输出至/data/err.log中。原data/err.log中的文件会被空文件覆盖。
cmd 2>> /data/err.log     这样就会将正确的信息显示在默认的输出设备上,而且每次的错误信息输入至err.log文件中,方便后面研究问题
对于输出既有正确信息又有错误信息的场景:
ls /err   /data  >f1   2>f2      则正确信息输出至f1 中,错误信息输出至f2 中
ls /err  /data   &>all.log   正确信息和错误信息都输出至all.log文件中。
或
ls /err  /data  >all.log  2>&1
ls /err  /data  2>all.log  >&2    注意次序!!
- 注意区分以下几项,哪个与众不同:
cmd > log  2>&1
cmd 2>&1  >log       此项与众不同
cmd  &>  log 
cmd 2>log  >&2
set –C 禁止将内容覆盖已有文件,但可追加
>| file  强制覆盖
set +C  允许覆盖

TIPS:
小技巧:> bigfile 效果是创建了一个bigfile的空文件。背后的原理是利用重定向标准输出的原理,重定向输出至bigfile文件,由于无任何输出结果,所以直接效果就是创建了一个空的bigfile文件。所以一个比较安全的创建空文件的方法是:\>> file .
原因:1. 假如file文件原来就存在,那么>> 不会覆盖原来的文件,只会在原文件基础上累加。
2.>> 不会刷新时间,touch命令会刷新时间
*** 非常重要: 假如  abc_link -> abc  (abc_link软链接abc),
那么我们> abc_link 的话,会直接覆盖源文件abc !!!!
<标准输入重定向
cat < file    file文件内容输入到cat命令上
cat < f1 > f2    f2里显示f1 内容的文件
cat < f1 > f1     清空f1 文件
cat < f1  >>f2  无限循环将f1文件累加至f2文件
二、tr命令(删除和转换字符)
tr [OPTION]... SET1 [SET2]
Translate, squeeze, and/or delete characters from standard input, writing to standard output.
tr 'a-z' 'A-Z'  #将输入的任意小写字符转换为大写,其他的字符保持原样
tr -c,–C  --complement:#use the complement of SET1;取字符集的补集;
tr -d,--delete: #delete characters in SET1, do not translate;删除所有属于第一字符集的字符
tr -s,--squeeze-repeats:#replace each input sequence of a repeated character that is listed in SET1 with a single occurrence of that character;把连续重复的字符以单独一个字符表示
tr -t,--truncate-set1:#first truncate SET1 to length of SET2;将第一个字符集对应字符转化为第二字符集
tr 'a-z' 'A-Z'  < /etc/fstab  将/etc/fstab这个文件中的小写字符转换为大写字符

r –d  abc < /etc/fstab   删除/etc/fstab这个文件中的abc字符

实验1:将df命令显示输出里的连续空格全部以一个空格输出
第一步:df > /data/test.out  将df命令的输出结果定向至/data/test.out文件中。
第二步:tr -s  ' ' < /data/test.out 完成

把多行发送给STDIN
使用“<<终止词”命令从键盘把多行重导向给STDIN
mail -s "PleaseCall"  admin@magedu.com  << END
>HiWang,
>
>Pleasegivemeacallwhenyougetin.Wemayneed
>todosomemaintenanceonserver1.
>
>Detailswhenyou'reon-site
>Zhang
>END
用END终止多行输入,并将内容以邮件方式发送给admin@magedu.com,邮件主题为PleaseCall
三、管道
管道(使用符号“|”表示)用来连接命令
命令1 | 命令2 | 命令3 | …
- 将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
- STDERR默认不能通过管道转发,可利用2>&1 或|& 实现
ls  /data /err 2>&1 | tr 'a-z'  'A-Z'
ls  /data /err   |&   tr 'a-z'  'A-Z' 
实验1: 随机产生的16位字符串,将其中的小写字符换成大写字符,并且删除无用的字符。
第一步:
openssl rand -base64 16 > /data/test.out  随机产生16位的字符串。并将其定向输出至文件中。
第二步:
tr  -dc  '[:alpha:]'   < /data/test.out | tr 'a-z'  'A-Z'   删除非字母的字符并将小写转换为大写
实验2: 计算1+2+3+4+.....+100 =
 echo {1..100}  | tr  '  '  '+'   | bc
管道中"-"符号
示例:
将/home 里面的文件打包,但打包的数据不是记录到文件,而是传送到stdout,经过管道后,将tar -cvf-/home 传送给后面的tar -xvf-, 后面的这个-则是取前一个命令的stdout,因此,就不需要使用临时file了
tar -cvf-/home | tar -xvf-
四、tee,重定向到多个目标
tee - read from standard input and write to standard output and files
 tee [OPTION]... [FILE]...
命令1 | tee [-a ] 文件名| 命令2
把命令1的STDOUT保存在文件中,同时做为命令2的输入,
tee -a, --append  #append to the given FILEs, do not overwrite,追加输出至文件中
使用场景:
- 保存不同阶段的输出
- 复杂管道的故障排除
- 同时查看和记录输出
五、练习
1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中
tr 'a-z' 'A-Z' < /etc/issue | tee -a /data/issue.out
2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中
who | tr 'a-z' 'A-Z' > /data/who.out
3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:
Hello, I am 用户名,The system version is here,pleasehelp me to check it ,thanks!
操作系统版本信息

4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开
ls /root  |  tr '\n'  ' '
5、计算1+2+3+..+99+100的总和
echo {1..100} | tr ' '  '+'  | bc
6、删除Windows文本文件中的‘^M’字符
7、处理字符串“xt.,l 1 jr#!$mn2 c*/fe3 uz4”,只保留其中的数字和空格
tr -dc [0-9][:space:] 
8、将PATH变量每个目录显示在独立的一行
echo $PATH | tr  ':'  '\n'
9、将指定文件中0-9分别替代成a-j
tr '0-9' 'a-j'   < 文件
10、将文件中每个单词(由字母组成)显示在独立的一行,并无空行

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号