标准输入和输出

程序:指令+数据
读入数据:Input
输出数据:Output
打开的文件都有一个fd: file descriptor (文件描述符)
Linux给程序提供三种I/O设备
标准输入(STDIN)-0 默认接受来自键盘的输入
标准输出(STDOUT)-1 默认输出到终端窗口
标准错误(STDERR)-2 默认输出到终端窗口
I/O重定向:改变默认位置

fd示例:

首先用tail -f 持续打开一个文件,这时已经给tail程序分配了一个文件描述符fd
然后在另一个终端上面进入 /etc/proc中找到它的 进程编号,可以用pidof tail来显示
然后进入到这个进程编号目录内,找到fd,查看其中的内容
程序tail 用ctrl+c关闭之后 这个进程编号便会消失,同时fd自然也就没有了(fd是在进程编号里面的文件夹)

  20:16[root@centos7 /data]# tail -f /data/1.t
2awda awdf###n  dwa /naaa

另一个终端:

  20:37[root@centos7 ~]# cd /proc
20:38[root@centos7 /proc]# ls
1      26     3018  6     6245  7698  8144  8329       cmdline      modules
10     27     36    6103  6250  7791  8150  8335       consoles     mounts
11     27378  37    6105  6292  7804  8163  8343       cpuinfo      mpt
12     27438  38    6107  6586  7810  8164  8352       crypto       mtrr
13     27526  39    6110  66    7814  8174  8354       devices      net
14     27537  47    6111  667   7816  8182  8359       diskstats    pagetypeinfo
14249  27551  4701  6135  6781  7820  8183  8372       dma          partitions
14674  27707  4886  6136  6782  7832  8185  8380       driver       sched_debug
16     27768  4888  6137  6785  7835  8187  8381       execdomains  schedstat
16316  27847  4889  6138  6786  7910  8196  8390       fb           scsi
1658   27890  4896  6141  6791  7915  8198  8391       filesystems  self
1661   28     4897  6143  6810  8     8201  8405       fs           slabinfo
1665   2886   49    6144  6811  8017  8202  8421       interrupts   softirqs
1709   2889   4901  6150  6814  8031  8206  8427       iomem        stat
1715   2890   4902  6160  682   8036  8208  8432       ioports      swaps
1791   2898   4908  6161  687   8039  8221  8547       irq          sys
1793   29     4910  6162  693   8066  8224  8566       kallsyms     sysrq-trigger
18     2902   4914  6165  699   8085  8226  8572       kcore        sysvipc
19     2905   4917  6170  7     8089  8227  8573       keys         timer_list
2      2906   4918  6174  7197  8092  8229  8625       key-users    timer_stats
20     2907   4919  6177  7209  8094  8232  8636       kmsg         tty
21     2908   4920  6178  7229  8106  8236  9          kpagecount   uptime
22     2909   4937  6180  7234  8110  8246  99         kpageflags   version
23     2910   4941  6181  7248  8116  8248  acpi       loadavg      vmallocinfo
23591  2911   5     6183  7537  8123  8267  asound     locks        vmstat
24     2984   50    6185  7605  8124  8311  buddyinfo  mdstat       zoneinfo
25     3      51    6203  7612  8133  8314  bus        meminfo
25713  3005   53    6235  7614  8135  8317  cgroups    misc
20:38[root@centos7 /proc]# cd `pidof tail`
20:38[root@centos7 /proc/27526]# ls
attr        coredump_filter  gid_map    mountinfo   oom_score      sched      statm
autogroup   cpuset           io         mounts      oom_score_adj  schedstat  status
auxv        cwd              limits     mountstats  pagemap        sessionid  syscall
cgroup      environ          loginuid   net         patch_state    setgroups  task
clear_refs  exe              map_files  ns          personality    smaps      timers
cmdline     fd               maps       numa_maps   projid_map     stack      uid_map
comm        fdinfo           mem        oom_adj     root           stat       wchan
20:38[root@centos7 /proc/27526]# cd fd
20:39[root@centos7 /proc/27526/fd]# ll
total 0
lrwx------. 1 root root 64 Mar 11 20:39 0 -> /dev/pts/1
lrwx------. 1 root root 64 Mar 11 20:39 1 -> /dev/pts/1
lrwx------. 1 root root 64 Mar 11 20:39 2 -> /dev/pts/1
lr-x------. 1 root root 64 Mar 11 20:39 3 -> /data/1.t
lr-x------. 1 root root 64 Mar 11 20:39 4 -> anon_inode:inotify

标准输出和标准错误重定向到其他文件或终端

  • STDOUT和STDERR可以被重定向到文件
    命令 操作符号 文件名
    支持的操作符号包括:

    把STDOUT重定向到文件
    2>把STDERR重定向到文件
    &>把所有输出重定向到文件
    ">"文件内容会被覆盖
    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 ; cal 2008 ) > all.txt
( cal 2007 ; cal 0000 2>&1) > all.txt

  • 可以用> 指向 /dev/null 将标准输出不显示
  • 可以用> 指向文件将文件内容清空 ,但注意有些shell可能不支持,比如csh,它只能用cat /dev/null > file 才可以
  • 追加到文件中可以用>> 也可以将两个命令用小括号括起来再使用
  • 同时,正确和错误信息同时追加到一个文件也有一个写发2>&1, 放在括号里面,注意与后面的那好几个写法区分
    20:55[root@centos7 /data]# (hostname; uname -r) > 1.t
    20:55[root@centos7 /data]# cat 1.t
    centos7.6test
    3.10.0-957.el7.x86_64
21:36[root@centos7 /data]# (ls /eraf /home 2>&1) >1.t
21:38[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang
  • \> 或者两个>> 也可以创建文件,但是因为>会把文件内容覆盖,(假如存在原始文件) 所以用>>更加安全
21:07[root@centos7 /data]# ls /eraf /home  > 1.t 2>&1
21:08[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang

21:08[root@centos7 /data]# ls /eraf /home  2>1.t 1>&2
21:08[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang

21:09[root@centos7 /data]# ls /eraf /home  2>&1 >1.t
ls: cannot access /eraf: No such file or directory
21:09[root@centos7 /data]# cat 1.t
/home:
zhang

21:12[root@centos7 /data]# ls /eraf /home  &>1.t
21:12[root@centos7 /data]# cat 1.t
ls: cannot access /eraf: No such file or directory
/home:
zhang

其中
1 cmd &> file
2 cmd > file 2>&1
3 cmd 2>&1 > file xxx
4 cmd 2>file 1>&2


问题:可以测试一下下面这几个命令的区别

ls /eraf /home 1>1.t 2>1.t
ls /eraf /home 1>>1.t 2>1.t
ls /eraf /home 2>>1.t 1>1.t
ls /eraf /home 2>1.t 1>1.t
ls /eraf /home 2>1.t 2>&1 1>1.t
ls /eraf /home 2>>1.t 2>&1 1>1.t
ls /eraf /home 2>&1 2>1.t 1>1.t
ls /eraf /home 2>&1 2>>1.t 1>1.t


tr转换

tr 转换和删除字符
tr [OPTION]... SET1 [SET2]
选项:
-c –C --complement:取字符集的补集
-d --delete:删除所有属于第一字符集的字符
-s --squeeze-repeats:把连续重复的字符以单独一个字符表示
-t --truncate-set1:将第一个字符集对应字符转化为第二字符集对应的字符

tr命令默认会让你用键盘输入,退出的时候不能按回车(按回车只是换行,增加了一个\n),需要用ctrl+d快捷键

[:alnum:]:字母和数字
[:alpha:]:字母
[:cntrl:]:控制(非打印)字符
[:digit:]:数字
[:graph:]:图形字符
[:lower:]:小写字母
[:print:]:可打印字符
[:punct:]:标点符号
[:space:]:空白字符
[:upper:]:大写字母
[:xdigit:]:十六进制字符

注意:tr转换中的字符串和通配符的区别在于:
tr转换里面不需要再加中括号了,直接代表一种字符
而通配符整体仅仅代表一个字符,外层需要再加中括号才可以

ls [:lower:]
ls [[:lower:]]

tr '[:lower:][:upper:]' '12'

注意:windows中的换行 包括两个字符,\c 和\n;linux中只有一个\n 它会自动把光标移动到开头
例如
a
b
c

windows: 
00000000 61 0d 0a 62 0d 0a 63
00000007

linux:
0000000 61 0a 62 0a 63 0a
0000006

利用tr计算 1+..100总和

09:45[root@centos7 ~]# echo {1..100} | tr ' ' '+' | bc
5050

09:46[root@centos7 ~]# seq -s + 100 |bc
5050

带有标准输入的部分程序:bc ,cat ,tr,mail
例如 bc < file1 file1中写有计算式,则屏幕上输出结果.

标准输入

使用 < 来重定向标准输入
某些命令能够接受从文件中导入的STDIN
tr ‘a-z’ ‘A-Z’< /etc/issue
该命令会把/etc/issue中的小写字符都转换成大写字符

tr –d abc < /etc/fstab
删除fstab文件中的所有abc中任意字符
tr -dc "abc" < /etc/fstab
只保留abc字符,其他的全部删除

cat 也有标准输入,只输入cat则会让你用键盘输入,按回车之后会再次显示出来,按ctrl+d可以离开
cat可以键盘输入后输出到文件
cat > file
zhang
duan
cat也可使用文件来代替键盘的输入,并同时输出到文件
cat < file1 > file2
但是需要注意下面的两个结果
cat < file1 > file1 :会把file1清0
cat < file1 >> file1:会一直追加file1中的内容到file1下面,必须停止否则文件会过大

22:02[root@centos7 /data]# tr 'abc' 'xyzmk'
abcdefaf
xyzdefxf

22:04[root@centos7 /data]# tr 'abcde' 'xyz'
abcderf
xyzzzrf

22:06[root@centos7 /data]# tr -t 'abcde' 'xyz' 
abcedrf
xyzedrf

单行重定向和多行重定向

使用“<<终止词”命令从键盘把多行重导向给STDIN
直到 终止词 位置的所有文本都发送给STDIN
有时被称为就地文本(heretext)
mail -s "Please Call" admin@magedu.com <<END

注意:终止词最后必须单独一行且前后不能有任何字符包括空格等
注意:单行重定向(也就是不写终止词的默认写法),每按一次回车,就会把结果重定向一次,而多行重定向只有终止词输入并回车之后才会把结果一次性输出,在此之前没有对文件做任何修改。
注意: 多行重定向内部可以用``来输入命令等,可以实现不同的结果

管道

管道(使用符号“|”表示)用来连接命令
命令1 | 命令2 | 命令3 | …
将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
STDERR默认不能通过管道转发,可利用2>&1 或 |& 实现
最后一个命令会在当前shell进程的子shell进程中执行
组合多种工具的功能
ls | tr ‘a-z’ ‘A-Z’

注意:管道前面命令必须要标准输出,管道后面命令必须要标准输入

管道重定向到多个目标

命令1 | tee [-a ] 文件名 | 命令2
把命令1的STDOUT保存在文件中,同时它也做为命令2的输入
-a 追加到文件中
使用:
保存不同阶段的输出
复杂管道的故障排除
同时查看和记录输出

注意:tee 后面必须跟文件

管道特殊用法-

示例:
将 /home 里面的文件打包,但打包的数据不是记录到文件,而是传送到stdout,经过管道后,将 tar -cvf - /home 传送给后面的 tar -xvf - , 后面的这个 - 则是取前一个命令的 stdout,因此,就不需要使用临时file了
tar -cvf - /home | tar -xvf -

本来的用法是:

tar -cvf 文件包名 /home
传输....
tar -xvf 文件包名

  • 将⽂件/etc/centos-release中每个单词(由字⺟组成)显⽰在独⽴⼀⾏,并⽆空⾏
    答案:cat /etc/centos-release |tr -cs '[:alpha:]' '\n'

  • cat file > file.copy & ,后台执行命令输出file内容到file.copy