标准IO和管道
1.标准输入和输出
- 程序:指令+数据
读入数据:input
输出数据:Output - 打开的文件都有一个fd:file descriptor(文件描述符)
- Linux给程序提供三种I/O设备
标准输入(STADIN)-0 默认接受来自键盘的输入
标准输出(STDOUT)-1 默认输出到终端窗口
标准错误(STDERR)-2 默认输出到终端窗口 - I/O重定向:改变默认位置
ls > /dev/pts/5 重定向到别的窗口(tty)
2. 把输出和错误重定向到文件
-
STDOUT和STDERR可以被重定向到文件
命令 操作符号 文件名
支持的操作符号包括:>
STDOUT重定向到文件
2> 把STDERR 重定向到文件
&> 把所有输出重定向到文件
ls /error /data >f1 >f2 -
>
文件内容会被覆盖
-
set -C 禁止将内容覆盖已有文件,但可追加
-
>
file 强制覆盖 -
set +C 允许覆盖
- 在原有内容基础上,追加内容
- 2> 覆盖重定向错误输出数据流
- 2>> 追加重定向错误输出数据流
- 标准输出和错误输出各自定向至不同位置
command > /path/to/file.out 2>/path/to/error.out
- 合并标准输出和错误输出为同一个数据流进行重定向
&>覆盖重定向
&>>追加重定向
COMMAND > /path/to/file.out 2>&1 (顺序很重要)
COMMAND >> /path/to/file.out 2>&1 - (): 合并多个程序的STDOUT
(cal 2007; cal2008) > all.txt
ls /error/ data >all.log 2>&1 = ls /error/data &>list.log 把标准输出重定向标准输出,标准输出在重定向到all.log 次序问题: ls /error /data 2>&1 2>all.log 正确显示在屏幕 错误显示在all.log中 A cmd > log 2&1 B cdm 2>&1 >log C cmd $>log D cmd 2>log >&2 B 显示效果与众不同 不在屏幕上显示 hostname > /dev/null 改口令: echo redhat | passwd --stdin wang &> /dev/null 标准输入:cat< /etc/hosts cat< f1 >f1 f1文件被破坏 cat>f2 不停的追加
3. tr命令:
-
tr转换和删除字符
-
tr [options]...set1 [set2]
-
选项:
-c -C --complement: 取字符集的补集 -d --delete : 删除所有属于第一字符集的字符(删除) -s --squeeze-repeats: 把连续重复的字符以单独一个字符表示 (压缩) -t --truncate-set1 :将第一个字符集对用字符转化为第二字符集对应的字符(替换) [:alnum:]:字母和数字 [:alpha:]:字母 [:cntrl:]:控制(非打印)字符 [:digit:]:数字 [:graph:]:图形字符 [:lower:]:小写字母 [:print:]:可打印字符 [:punct:]:标点符号 [:space:]:空白字符 [:upper:]:大写字母 [:xdigit:]:十六进制字符
-
示例:
tr 'a-z' 'A-Z' < /etc/fstab >f1.log
`tr 'adc' '1234'` adcdfd //输入内容 1232f2 //转换的内容
4.从文件中导入STDIN
- 使用<来重定向标准输入
- 某些命令能够接受从文件中导入的STDIN
tr 'a-z' 'A-Z'< /etc/issue
该命令会把/etc/issue中的小写字符转换为大写字符 - tr -d adb </etc/fstab 删除fstab文件中的所有abc中任意字符
- cat >file
hello
world
按Ctrl+d离开,可以使用文件来代替键盘的输入
单行重定向enter才能重定向 - cat > filea <fileb
- cat < file1 >> file1
5.把多行发送给STDON
-
使用“<< 终止词” 命令从键盘吧多行重定向给STDIN
直到 终止词 位置的所有文本都发送给STDIN
有时被称为就地文本(heretext)eg:发邮件
mail -s "hello" wang hi //输入内容 how are you how ole are you . //.结束退出 su - wang 切换用户 mail 查看邮件
6. 管道pipe
cdm1 | cmd2 cmd1 stdout cmd2 stdin
- 管道(使用符号"|"表示)用来连接命令
命令1|命令2|命令3…
将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
STDERR默认不能通过管道转发,可利用2&>1或|&实现
最后一个命令会在当前shell进程的子shell进程中执行用来
组合多种工具的功能
ls | tr ‘a-z’ ‘A-Z’ - less : 一页一页地查看输入
ls -l /etc | less - mail: 通过电子邮件发送输入
echo "test enmail " | mail -s “test” user@example.com - lpr: 把输入发送给打印机
echo "test print " | lpr -P printer_name
eg: homename | tr 'a-z' 'A-Z' | tr -d '.' cat mail.txt | mail -s 'hello' wang ls /boot /error 2&>1 |=tr 'a-z' 'A-Z' ls /boot /error |& tr 'a-z' 'A-Z' 新 df | tr -s ' ' ':' 面试题: 计算1+2+...+100 echo {1..100} | tr ' ' '+' | bc seq -s + 1 100 | bc
7.管道-符号
- 示例:
将/home里面带的文件打包,但打包的数据不是记录到文件,而是传送到stdout,经过管道后,将
tar -cvf - /home 传送给后面的tar -xvf - ,后面的这个- 则是取前一个命令的stdout,因此,就不需要使用临时file了 - tar -cvf - /home | tar -xvf -
8.重定向到多个目标(tee)(可以重定向到文件中,又可以在屏幕中显示
- 命令1| tee [-a] 文件名 | 命令2
把命令1的STDOUT保存在文件中,作为命令2的输入
-a 追加 - 使用:
保存不同阶段的输出
复杂管道的故障排除
同时查看和记录输出
eg: ls | tee ls.log who |tee -a ls.log (-a 追加) ls | tee ls.log | tr -d '\n'