• Linux基础学习笔记(十二)——管道命令


    前言

    上一篇博客简述了一下Linux中的输入输出重定向,这篇博客总结一下Linux中的管道命令,为后面的文件格式化,shell学习做一个基础,对应《鸟哥的Linux私房菜》第十章10.6的内容

    管道命令

    其实管道命令,就是使用|这个界定符号,这个命令默认仅能处理经由前一个指令传过来的正确信息,也就是上一篇博客中提到的standard output信息,对于standard error 标准错误信息,默认是没法处理的。
    在这里插入图片描述

    如果想要管道命令之后的某个命令,可以处理标准错误输出,可以将标准输出和标准错误输出均重定向到一处,这个在上一篇博客中有介绍,这里不做说明了。

    下面总结的命令,是在管道命令的基础上进行一些数据处理

    cut命令

    主要用于数据的截取,从列的角度进行数据截取,上一篇博客中的grep命令是从行的角度过滤数据。
    在这里插入图片描述

    实例

    ##将export输出的结果,从第12个字符开启截取,一直截取到末尾,输出结果
    [root@localhost shell-learn]# export | cut -c 12-
    CLASSPATH=".:%JAVA_HOME%/lib/dt.jar:%JAVA_HOME%/lib/tools.jar"
    HISTCONTROL="ignoredups"
    HISTSIZE="1000"
    HOME="/root"
    HOSTNAME="localhost.localdomain"
    JAVA_HOME="/usr/local/software/java/jdk1.8.0_191"
    LANG="zh_CN.UTF-8"
    LESSOPEN="||/usr/bin/lesspipe.sh %s"
    LOGNAME="root"
    ###...以下输出结果省略
    # 用如下命令,可以达到同等效果
    [root@localhost shell-learn]# export | cut -d ' ' -f 3
    CLASSPATH=".:%JAVA_HOME%/lib/dt.jar:%JAVA_HOME%/lib/tools.jar"
    HISTCONTROL="ignoredups"
    HISTSIZE="1000"
    HOME="/root"
    ###...以下输出结果省略
    
    ##从last命令的输出结果中,截取登录的用户名
    [root@localhost shell-learn]# last | cut -d ' ' -f 1
    reboot
    root
    reboot
    root
    ###...以下输出结果省略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    sort,wc,uniq命令

    sort命令

    sort可以帮我们进行数据的排序,而且可以根据不同的数据形态来排序
    在这里插入图片描述

    如果要详细探讨每一个命令属性,这个就有点麻烦了,《鸟哥的Linux私房菜》也只介绍了简单的几个实例

    ## 读取个人账号信息数据,并排序,默认按第一个数据来排序
    [root@localhost shell-learn]# cat /etc/passwd | sort
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    dbus:x:81:81:System message bus:/:/sbin/nologin
    esuser:x:1001:1001::/home/esuser:/bin/bash
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    games:x:12:100:games:/usr/games:/sbin/nologin
    halt:x:7:0:halt:/sbin:/sbin/halt
    ###...以下输出结果省略
    
    ##读取个人账号信息数据,并以第三列数据进行排序
    ### -t指定分割符,-k指定分割之后的排序字段
    [root@localhost shell-learn]# cat /etc/passwd | sort -t ':' -k 3
    root:x:0:0:root:/root:/bin/bash
    esuser:x:1001:1001::/home/esuser:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    ###...以下输出结果省略
    ## 可以看到上面的结果11 排在1001之后,这没按照数字排序,如果按照数字排序,需要指定-n选项
    [root@localhost shell-learn]# cat /etc/passwd | sort -t ':' -k 3 -n
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    ###...以下输出结果省略
    
    ## 通过last读取登录数据,按照列切分之后,得到登录账号数据,并排序
    [root@localhost shell-learn]# last | cut -d ' ' -f1 | sort
    reboot
    ###...以下输出结果省略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    uniq命令

    类似SQL语句中的distinct,这里是对排序之后的结果进行去重
    在这里插入图片描述

    实例

    ## 通过last命令读取登录信息,并根据空格进行分割,然后读取登录账号,排序,去重。
    [root@localhost shell-learn]# last | cut -d ' ' -f1 | sort | uniq
    ##输出结果
    reboot
    root
    wtmp
    ## 通过last命令读取登录信息,并根据空格进行分割,然后读取登录账号,排序,去重,并统计登录次数,类似SQL中的count。
    [root@localhost shell-learn]# last | cut -d ' ' -f1 | sort | uniq -c
          1 
         65 reboot
         87 root
          1 wtmp
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    wc命令

    wc命令用于统计文件里头多少字符,多少行,多少字符信息。
    在这里插入图片描述

    实例

    # 读取man_db.conf中的数据,并进行字符统计
    # 输出的三个结果中,分别表示[行,字数,字符数]
    [root@localhost shell-learn]# cat /etc/man_db.conf | wc
        131     723    5171
    # 读取last命令中登入系统的总人数
    ##这里通过grep -v命令,去除了很多无用的登录记录信息
    [root@localhost shell-learn]# last | grep [a-zA-Z] |grep -v 'wtmp' | grep -v 'reboot' | \
    > grep -v 'unknown' | wc -l
    87
    # 读取当前系统中有多少个账户
    [root@localhost shell-learn]# cat /etc/passwd | wc -l
    21
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    双向重定向——tee命令

    之前我们在利用重定向命令输出的时候,将数据流重定向到某个文件之后,屏幕的标准输出就木有了,tee命令可以将数据流分送到文件和屏幕
    在这里插入图片描述

    实例

    #使用tee命令之后,可以将标准输出备份到文件的同时,也不影响数据流后续的标准输出
    ## 该命令执行完成之后,last.txt中会存有一份last命令的标准输出,后面的cut也能得到正常结果
    [root@localhost shell-learn]# last | tee last.txt | cut -d ' ' -f1
    
    • 1
    • 2
    • 3

    字符替换命令

    除了使用dos2unix和unix2dox来进行换行符的转换之外,linux还提供了其他字符转换的命令

    tr命令

    用来删除信息中的一些文件或者进行文字替换
    在这里插入图片描述

    实例

    # 将last命令的输出结果中,小写字母转成大写字母
    [root@localhost shell-learn]# last | tr '[a-z]' '[A-Z]'
    ROOT     PTS/0        192.168.0.103    SUN JUL 31 09:53   STILL LOGGED IN   
    ROOT     TTY1                          SUN JUL 31 09:53   STILL LOGGED IN   
    REBOOT   SYSTEM BOOT  3.10.0-1160.EL7. SUN JUL 31 09:52 - 11:31  (01:38)
    ###...以下输出结果省略
    ## 将cat /etc/passwd命令的输出结果中的冒号删除
    [root@localhost shell-learn]# cat /etc/passwd | tr -d ':'
    rootx00root/root/bin/bash
    binx11bin/bin/sbin/nologin
    daemonx22daemon/sbin/sbin/nologin
    ###...以下输出结果省略
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    col命令

    这个命令用来简单的将tab键替换成空格
    在这里插入图片描述

    实例

    #cat -A显示所有特殊字符,col -x 将tab替换成空格,最后的more命令显示的内容没有^I字符
    [root@localhost shell-learn]# cat /etc/man_db.conf | col -x | cat -A | more
    
    • 1
    • 2

    join命令

    类似SQL中的join,如果两个文件中的数据列相同,则通过join命令只输出一列
    在这里插入图片描述

    实例

    # 通过head命令查看,/etc/passwd和/etc/shadow两个文件中的第一列是相同的
    [root@localhost shell-learn]# head -n 3 /etc/passwd /etc/shadow
    ==> /etc/passwd <==
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    
    ==> /etc/shadow <==
    root:$6$FI.UzpVEoa1js0tM$j2khNaltnlIWqz7/aXd7scHOIrwJiVxIh.df9Da1gMQYdxBXL1O6odGDZNhjfMSfxb1u39jGXQ6/.o1f0duRS0::0:99999:7:::
    bin:*:18353:0:99999:7:::
    daemon:*:18353:0:99999:7:::
    #通过join命令查询之后,第一列只显示一次
    [root@localhost shell-learn]# join -t ':' /etc/passwd /etc/shadow | head -n 3
    root:x:0:0:root:/root:/bin/bash:$6$FI.UzpVEoa1js0tM$j2khNaltnlIWqz7/aXd7scHOIrwJiVxIh.df9Da1gMQYdxBXL1O6odGDZNhjfMSfxb1u39jGXQ6/.o1f0duRS0::0:99999:7:::
    bin:x:1:1:bin:/bin:/sbin/nologin:*:18353:0:99999:7:::
    daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:18353:0:99999:7:::
    
    # /etc/passwd中的第四列和/etc/group文件中的第三列内容是一致的
    [root@localhost shell-learn]# head -n 3 /etc/passwd /etc/group
    ==> /etc/passwd <==
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    
    ==> /etc/group <==
    root:x:0:
    bin:x:1:
    daemon:x:2:
    # 通过join指定匹配的列,-1指定第一个文件要匹配的列,-2指定第二个文件要匹配的列
    [root@localhost shell-learn]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3
    0:root:x:0:root:/root:/bin/bash:root:x:
    1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:
    2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    需要特别注意的是,在使用join之前,数据最好已经经过排序

    paste命令

    paste命令比join命令要简单,paste是直接将两行数据贴在一起,中间tab键隔开,不管这两行数据中是否有可匹配的字段
    在这里插入图片描述

    实例

    ## 将/etc/passwd /etc/shadow文件同一行拼接在一起,并显示前三行
    [root@localhost shell-learn]# paste /etc/passwd /etc/shadow | head -n 3
    root:x:0:0:root:/root:/bin/bash	root:$6$FI.UzpVEoa1js0tM$j2khNaltnlIWqz7/aXd7scHOIrwJiVxIh.df9Da1gMQYdxBXL1O6odGDZNhjfMSfxb1u39jGXQ6/.o1f0duRS0::0:99999:7:::
    bin:x:1:1:bin:/bin:/sbin/nologin	bin:*:18353:0:99999:7:::
    daemon:x:2:2:daemon:/sbin:/sbin/nologin	daemon:*:18353:0:99999:7:::
    
    • 1
    • 2
    • 3
    • 4
    • 5

    expand命令

    将tab键的字符转成空格符
    在这里插入图片描述

    实例

    #从man_db.conf文件中,以MANPATH开头的数据
    [root@localhost shell-learn]# grep '^MANPATH' /etc/man_db.conf | head -n 3
    MANPATH_MAP	/bin			/usr/share/man
    MANPATH_MAP	/usr/bin		/usr/share/man
    MANPATH_MAP	/sbin			/usr/share/man
    ##tab键的符号,在cat -A之后,通过^I显示出来
    [root@localhost shell-learn]# grep '^MANPATH' /etc/man_db.conf | head -n 3 | cat -A
    MANPATH_MAP^I/bin^I^I^I/usr/share/man$
    MANPATH_MAP^I/usr/bin^I^I/usr/share/man$
    MANPATH_MAP^I/sbin^I^I^I/usr/share/man$
    ## 这里设定的是6个字符代表一个tab符号
    [root@localhost shell-learn]# grep '^MANPATH' /etc/man_db.conf | head -n 3 | expand -t 6 | cat -A
    MANPATH_MAP /bin              /usr/share/man$
    MANPATH_MAP /usr/bin          /usr/share/man$
    MANPATH_MAP /sbin             /usr/share/man$
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    文件拆分命令

    split命令是linux中的文件拆分命令
    在这里插入图片描述

    实例

    [root@localhost shell-learn]# cd /tmp
    ##指定以300k的大小进行文件拆分,前缀为services
    [root@localhost tmp]# split -b 300k /etc/services services
    [root@localhost tmp]# ll
    总用量 656
    -rw-r--r--. 1 root root 307200 731 14:33 servicesaa
    -rw-r--r--. 1 root root 307200 731 14:33 servicesab
    -rw-r--r--. 1 root root  55893 731 14:33 servicesac
    ## 将上述三个文件,合并为一个文件 使用数据流重定向即可完成
    [root@localhost tmp]# cat services* >> servicesback
    [root@localhost tmp]# ll
    总用量 1312
    -rw-r--r--. 1 root root 307200 731 14:33 servicesaa
    -rw-r--r--. 1 root root 307200 731 14:33 servicesab
    -rw-r--r--. 1 root root  55893 731 14:33 servicesac
    -rw-r--r--. 1 root root 670293 731 14:36 servicesback
    ## 将 ls -al /的输出信息,每10行记录生成一个文件
    [root@localhost tmp]# ls -al / | split -l 10 - lssplitfile
    [root@localhost tmp]# wc -l lssplitfile*
      10 lssplitfileaa
      10 lssplitfileab
       5 lssplitfileac
      25 总用量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    参数替换

    xargs是管道命令中,控制传递个下一个命令的参数个数
    在这里插入图片描述

    实例

    #正常的id命令可以显示用户组别等详细信息
    [root@localhost tmp]# id
    uid=0(root) gid=0(root)=0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
    [root@localhost tmp]# id root
    uid=0(root) gid=0(root)=0(root)
    ## 可以通过截取/etc/passwd文件得到用户信息
    [root@localhost tmp]# cut -d ':' -f 1 /etc/passwd | head -n 3
    root
    bin
    daemon
    # 是否可以直接通过管道,将这里两个命令结合,达到输出所有用户组别信息的目的?
    ##取出了三个,但是只有一个,因为前面的命令输出了三个用户,但是id只能接受一个参数,下述指令相当于只执行了id
    [root@localhost tmp]# cut -d ':' -f 1 /etc/passwd | head -n 3 | id
    uid=0(root) gid=0(root)=0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
    
    ##换一种姿势也不行
    [root@localhost tmp]# id $(cut -d ':' -f 1 /etc/passwd | head -n 3)
    id: 额外的操作数 "bin"
    Try 'id --help' for more information.
    
    ##通过xargs指示传递给下一个命令的那参数,一个一个的给。可以得到正确结果
    [root@localhost tmp]# cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -n 1 id
    uid=0(root) gid=0(root)=0(root)
    uid=1(bin) gid=1(bin)=1(bin)
    uid=2(daemon) gid=2(daemon)=2(daemon)
    #加上 -p 选项,每次都会询问用户是否确认执行
    [root@localhost tmp]# cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -p -n 1 id
    id root ?...y
    uid=0(root) gid=0(root)=0(root)
    id bin ?...y
    uid=1(bin) gid=1(bin)=1(bin)
    id daemon ?...y
    uid=2(daemon) gid=2(daemon)=2(daemon)
    #将所有/etc/passwd内的账号都以id进行查阅,但差到sync就结束
    [root@localhost tmp]# cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -e'sync' -n 1 id
    uid=0(root) gid=0(root)=0(root)
    uid=1(bin) gid=1(bin)=1(bin)
    uid=2(daemon) gid=2(daemon)=2(daemon)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    xargs是一个比较好用的工具,可以将原来本身不支持管道命令的操作一起级联起来。

    关于-

    在管道命令中,有时候会出现-这是因为,有时候管道命令会使用到前一个指令的标准输出作为本地的输入,但是这个时候用文件作为中转有些不方便,因此 - 其实就代表命令的标砖输出。

    # 例如:我们要打包一个文件夹/var/log到当前目录下通常分为两步
    tar -cvf log.tar /var/log/
    zip -r log.tar.zip log.tar
    rm -rf log.tar
    # 写成一条语句
    tar -cvf log.tar /var/log/ && zip -r log.tar.zip log.tar && rm -rf log.tar
    ## 可以看到第一条语句的log.tar就是第二条语句的输入,可以用 - 来取代这个输入
    tar -cvf – /var/log | zip -r log.zip -
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    总结

    起于管道命令,基于管道命令总结了一堆结合管道命令的实例

  • 相关阅读:
    dpdk ring多/单生产者、多/单消费者
    电商API接口商品详情获取示例
    【Java八股40天-Day6】 多线程及高并发1
    算法训练第五十八天
    【学习笔记】Java 一对一培训(2.1)Java基础语法
    openharmony容器组件之Flex
    MongoDB实战之快速开始
    信号和槽机制
    神经网络图像处理实例图,神经网络图像识别算法
    如何批量将长视频分割成短视频?详细操作步骤一目了然
  • 原文地址:https://blog.csdn.net/liman65727/article/details/126085904