美文网首页
重定向和管道

重定向和管道

作者: 毛利卷卷发 | 来源:发表于2018-06-05 16:53 被阅读0次

    输入和输出

    程序是由指令加数据组成的,一般情况下都会有输入(Input)和输出(Output),当你由程序打开一个文件的时候就会产生一个文件描述符(file descriptor)。在Linux中有三种IO设备,分别是:

    stdin:标准输入,默认情况下接受来自键盘的输入
    stdpout:标准输出,默认情况下输出到终端的窗口
    stderr:错误输出,默认情况输出终端的窗口

    重定向

    在默认情况下,stdout和stderr都是被输出到终端的,但是有时候,我们需要将其输出到指定的终端或者指定的文件记录下来,所有就有了重定向的概念

    输出重定向

    重定向符号 若文件不存在 若文件存在
    > 创建,并将正确的输出写入到文件中 将正确的内容覆盖至目标文件
    >> 创建,并将正确输出写入到文件中 将正确的内容追加至目标文件
    2> 创建,并将错误输出写到文件中 将错误的内容覆盖至目标文件
    2>> 创建,并将错误输出写到文件中 将错误的内容追加至目标文件
    &> 创建,并将所有输出写到文件中 将所有的内容覆盖至目标文件
    &>> 创建,并将所有输出写到文件中 将所有的内容追加至目标文件

    在使用>>的时候,可能不小心就敲成>,就会造成有些重要数据的被覆盖从而丢失,这时候就可以通过set -C来禁止内容覆盖,因为系统默认是set +C允许覆盖,还可以使用>|来强制覆盖

    [root@centos6 app]# echo nihao > nihao.txt
    [root@centos6 app]# cat nihao.txt 
    nihao
    [root@centos6 app]# set -C
    [root@centos6 app]# echo hello > nihao.txt 
    -bash: nihao.txt: cannot overwrite existing file
    [root@centos6 app]# echo hello >| nihao.txt 
    [root@centos6 app]# cat nihao.txt 
    hello
    

    标准输出和错误输出可以重定向至不同的位置

    [fanjie@centos6 ~]$ find /etc/ -name "*.conf" > /app/a.out 2> /app/b.err
    

    可以使用()合并多个命令执行的结果到一个文件中

    [root@centos6 app]# (cat /etc/passwd;cat /etc/shadow) > /app/etc.txt
    

    正确输出和错误输出之间的相互切换

    使用2>&1将错误结果转换正确结果

    [fanjie@centos6 app]$ cat find.out |wc -l
    406
    [fanjie@centos6 app]$ find /etc/ -name "*.conf" > find.out 2>&1
    [fanjie@centos6 app]$ cat find.out |wc -l
    420
    

    使用1>&2将正确结果转换错误结果

    [fanjie@centos6 app]$ cat find.out |wc -l
    14
    [fanjie@centos6 app]$ find /etc/ -name "*.conf" 2> find.out 1>&
    2
    [fanjie@centos6 app]$ cat find.out |wc -l
    420
    

    以上两种方法其实和下面的方式的输出结果是一样的,这里使用的是&>

    [fanjie@centos6 app]$ find /etc/ -name "*.conf" &> find.out
    [fanjie@centos6 app]$ cat find.out |wc -l
    420
    

    输入重定向

    从文件中导入到stdin

    使用<来重定向标准输入,下面的例子就是将/etc/default/useradd的内容全部转换成大写

    [root@centos6 app]# tr 'a-z' 'A-Z' < /etc/default/useradd 
    # USERADD DEFAULTS FILE
    GROUP=100
    HOME=/HOME
    INACTIVE=-1
    EXPIRE=
    SHELL=/BIN/BASH
    SKEL=/ETC/SKEL
    CREATE_MAIL_SPOOL=YES
    

    比如现在我们想把/etc/fstab里面的abc中的任意字符删掉

    [root@centos6 app]# tr -d "abc" < /etc/fstab
    

    可以使用cat新建一个文件,然后键入内容,输入完成用Ctrl + d来完成

    [root@centos6 app]# cat > test.txt
    nihao
    hello
    [root@centos6 app]# cat test.txt 
    nihao
    hello
    

    也可以将文件的内容输入到另一个文件,相当于是复制了一个文件

    [root@centos6 app]# echo nihao > 1.txt
    [root@centos6 app]# cat 1.txt 
    nihao
    [root@centos6 app]# cat >2.txt < 1.txt 
    [root@centos6 app]# cat 2.txt 
    nihao
    

    多行发送给stdin

    [root@centos6 app]# cat > file << EOF
    > nihao 
    > hello
    > EOF
    [root@centos6 app]# cat file
    nihao 
    hello
    

    垃圾桶

    当有的输出结果我们不需要时,就可以将其输出到/dev/null下

    tr

    转换和删除字符,常用选项:

    • -t:将第一个字符集对应的字符转换为第二个字符集对应的字符,默认
    • -d:删除所有第一字符集的字符
    • -s:把连续重复的字符以单独一个字符表示
    • -c:取字符集的补集
    [root@centos6 app]# echo abcabc |tr ab x
    xxcxxc
    [root@centos6 app]# echo 1234567890 |tr 123 abcdef
    abc4567890
    
    [root@centos6 app]# echo aaabcbbbde |tr -s ab x
    xcxde
    [root@centos6 app]# echo aaabcbbbde |tr -s ab
    abcbde
    
    [root@centos6 app]# cat -A tr.txt 
    abcabc$
    [root@centos6 app]# cat tr.txt |tr -c ab x
    abxabxx[root@centos6 app]# 
    

    管道

    管道是用来连接命令的,将前面命令的正确输出给后面命令的标准输入。stderr默认不能通过管道转发,可以利用2>&1或者是|&实现

    [root@centos7 app]$ find /etc/ -name "*.conf" 2>&1  |wc -l
    344
    [root@centos7 app]$ find /etc/ -name "*.conf" |& wc -l
    344
    

    less

    可以用man下的快捷键操作,相当于把输出结果放在man下查看

    tee

    重定向到多个目标,把/etc/default/useradd的内容转换成大写保存一份,然后在终端输出结果

    [root@centos6 app]# cat /etc/default/useradd |tee useradd.txt |tr a-z A-Z
    # USERADD DEFAULTS FILE
    GROUP=100
    HOME=/HOME
    INACTIVE=-1
    EXPIRE=
    SHELL=/BIN/BASH
    SKEL=/ETC/SKEL
    CREATE_MAIL_SPOOL=YES
    
    [root@centos6 app]# cat useradd.txt 
    # useradd defaults file
    GROUP=100
    HOME=/home
    INACTIVE=-1
    EXPIRE=
    SHELL=/bin/bash
    SKEL=/etc/skel
    CREATE_MAIL_SPOOL=yes
    

    练习

    1. 将/etc/issue文件中的内容转换为大写后保存至/app/issue.out文件中

      [root@centos6 app]# cat /etc/issue |tr a-z A-Z > /app/issue.out
      
    2. 将当前系统登录用户的信息转换为大写后保存至/app/who.out文件中

      [root@centos6 app]# who am i |tr a-z A-Z > /app/who.out
      
    3. 一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:
      Hello, I am 用户名,The system version is here,please help me to check it thanks!
      操作系统版本信息

      [fanjie@centos7 ~]$ mail -s "help" root <<EOF
      Hello, I am $(whoami),The system version is here,please help me to check it thanks!
      `cat /etc/redhat-release`
      EOF
      
    4. 将/root/下文件列表,显示成一行,并文件名之间用空格隔开

      [root@centos6 app]# ls /root/ |tr [:space:] ' '
      anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog Music Pictures Public Templates tr Videos 
      [root@centos6 app]# ls /root/ |tr '\n' ' '
      anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog Music Pictures Public Templates tr Videos 
      
    5. 计算1+2+3+..+99+100的总和

      [root@centos6 app]# echo {1..100} |tr [:blank:] + |bc
      5050
      [root@centos6 app]# echo {1..100} |tr ' ' + |bc
      5050
      
    6. 删除Windows文本文件中的‘^M’字符

      [root@centos6 app]# cat windows.txt |tr -d '\r' |cat -A
      a$
      b$
      c$
      d$
      e$
      
    7. 处理字符串“xt.,l 1 jr#!$mn 2 c*/fe 3 uz 4”,只保留其中的数字和空格

      [root@centos6 app]# echo xt.,l 1 jr#-Amn 2 c*/fe 3 uz 4 |tr -d [:alpha:][:punct:]
       1  2  3  4
      [root@centos6 app]# echo xt.,l 1 jr#-Amn 2 c*/fe 3 uz 4 |tr -cd [:digit:][:blank:]
       1  2  3  4
      
    8. 将PATH变量每个目录显示在独立的一行

      [root@centos6 app]# echo $PATH |tr : '\n'
      
    9. 将指定文件中0-9分别替代成a-j

      [root@centos6 app]# echo 9876543210 |tr 0-9 a-j
      jihgfedcba
      
    10. 将文件中每个单词(由字母组成)显示在独立的一行,并无空行

      [root@centos6 app]# echo nihao hello fanjie |tr [:blank:] '\n'
      

    相关文章

      网友评论

          本文标题:重定向和管道

          本文链接:https://www.haomeiwen.com/subject/jjkmsftx.html