1、什么是管道命令

linux命令执行的时候有输出数据,如果这些数据必须经过几次操作之后才能得到我们想要的格式,这就可以使用管道 命令(pipe)来完成了。

假设我们想知道 /etc/ 下有多少文件,可以使用 ls /etc/ 来查询,不过因为文件太多了,输出占满整个屏幕,导致最开始是什么文件看不到了,这就可以通过管道命令结合 less 指令来达成

ls -al /etc/ | less # 这样可以慢慢看,"|"就是管道的意思,"|"把ls -al /etc的输出做为less的输入

ls -al /etc # 这个会一下子占满整个屏幕,输出一闪而过

上面命令行里的「|」竖线就是一个管道,它的功能是将前一个命令(ls -al /etc/)的输出,作为后一个命令(less)的输入,从这功能描述,可以看出管道传输数据是单向的。

如此一来, ls -al 命令输出后的内容,能够被less读取,并且利用 less 的功能,可以前后翻动相关信息。

上面的管道命令可以用下图来表示:

在每个管道后面接的第一个必定是「命令」,而且这个命令必须能接受输出的数据才可以,这样的命令则是「管道命令」,例如 less、more、head、tail,grep,xargs等都是可以接受输出数据的管道命令。而 ls、cp、mv 等就不是管道命令了,因为他们不不会接受来自其他命令的输出数据

2、截取命令cut、grep

2.1 cut命令:把一段数据通过某个分隔符进行分隔,然后取出我们想要的段

cut命令参数:

  • d:后面接分割字符。与 -f 一起使用
  • f:依据 -d 的分割字符将一段信息分区成数段,用 -f 取出第几段的意思
  • c:以字符(characters)的单位取出固定字符区间

格式: cut -d ‘分割字符’ -f fields # 用于有特定分割字符

# 范例 1:将 PATH 变量取出,我要找出第 5 个路径
[root@k8s-node ~]$ echo ${PATH}
/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mrcode/.local/bin:/home/mrcode/bin
# 数量是从 1 开始,不是从 0 哟
[root@k8s-node ~]$ echo ${PATH} | cut -d ':' -f 5
/usr/sbin

# 取出第 5 个和第 6 个
[root@k8s-node ~]$ echo ${PATH} | cut -d ':' -f 5,6
/usr/sbin:/home/mrcode/.local/bin


# 范例 2 :将 export 输出的信息,取得第 12 字符以后的所有字符串
[root@k8s-node ~]$ export
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/home/mrcode"
declare -x HOSTNAME="study.centos.mrcode"
...

# 以上数据每个都是排列整齐的,有着 declare -x 前缀
# 那么想要把前缀去掉,就可以这样做
[root@k8s-node ~]$ export | cut -c 12-
HISTCONTROL="ignoredups"
HISTSIZE="1000"
HOME="/home/mrcode"
# 使用 12-15 则是截取出这个区间的字符
# 使用 12 则只截取 12 这个字符

# 范例 3 :用 last 将显示的登陆者信息,仅留下用户名
[root@k8s-node ~]$ last
# 账户         终端机                    登录 IP                    日期时间                        
mrcode   pts/1        192.168.0.105    Mon Dec  2 01:25   still logged in   
mrcode   pts/0        192.168.0.105    Mon Dec  2 01:25   still logged in   
mrcode   pts/1        192.168.0.105    Mon Dec  2 00:21 - 01:12  (00:51)  
# 用空格分隔的数据,那么可以这样做
[root@k8s-node ~]$ last | cut -d ' ' -f 1
mrcode
mrcode
mrcode
# 其实 账户和终端机之间的空格有好几个,并不是一个所以使用下面的命令并不能把 终端机一列也提取出来
last | cut -d ' ' -f 1,2

2.2 grep命令:分析数据的每一行,如果这行包括我们想要的关键词,则取出来

grep命令参数:
a:将 binary 文件以 text 文件的方式搜索数据
c:计算找到「搜索字符」的次数
i:忽略大小写
n:输出行号
v:反向选择,显示出没有搜索字符串的那一行数据
–color:可以将找到的关键词部分加上颜色显示

格式:grep [-acinv] [–color=auto] ‘搜索的字符串’ filename

# 范例 1:将 last 中,有出现 root 的那一行找出来
[root@k8s-node ~]$ last | grep 'root'
root     tty3                          Sun Oct  6 23:16 - crash  (22:40)    
root     tty4                          Fri Oct  4 22:48 - 22:48  (00:00)  
# 会发现 root 被高亮颜色了,我们时候 type 命令查看,发现被自动加上了 color 参数
[root@k8s-node ~]$ type grep
grep is aliased to 'grep --color=auto'

# 范例 2:与 范例 1 相反,不要 root 的数据
[root@k8s-node ~]$ last | grep -v 'root'
mrcode   pts/1        192.168.0.105    Mon Dec  2 01:25   still logged in   
mrcode   pts/0        192.168.0.105    Mon Dec  2 01:25   still logged in   
mrcode   pts/1        192.168.0.105    Mon Dec  2 00:21 - 01:12  (00:51)
reboot   system boot  3.10.0-1062.el7. Fri Oct  4 18:47 - 03:43  (08:56)

# 范例 3:在 last 的输出信息中,只要有 root 就取出,并且只取第一栏
# 结合 cut 命令取出第一栏
[root@k8s-node ~]$ last | grep 'root' | cut -d ' ' -f 1
root
root

# 范例 4:取出 /etc/man_db.conf 内涵 MANPATH 的那几行
[root@k8s-node ~]$ grep 'MANPATH' /etc/man_db.conf
# MANDATORY_MANPATH                     manpath_element
# MANPATH_MAP           path_element    manpath_element

3、排序命令sort、wc、uniq

3.1 sort命令:可以根据字符或者数字大小来排序

sort命令参数:
f:忽略大小写的差异
b:忽略最前面的空格符
M:以月份的名字来排序,例如 JAN、DEC 等排序方法
n:使用纯数字进行排序,默认是以文字形态来排序
r:反向排序
u:uniq,相同的数据中,仅出现一行代表,也就是去重
t:分隔符,预设使用 「tab」来分割
k:以那个区间(field)来进行排序

格式:sort [-fbMnrtuk] [file or stdin]

# 范例 1:个人账户都记录在 /etc/passwd 下,将账户进行排序
[root@k8s-node  ~]$ cat /etc/passwd | sort
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
chrony:x:993:990::/var/lib/chrony:/sbin/nologin
# 可以看到按字符排序了

# 范例 2:/etc/passwd 内容是以 : 来分割的,想使用第三栏进行排序
[root@k8s-node  ~]$ cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
mrcode:x:1000:1000:mrcode:/home/mrcode:/bin/bash
qemu:x:107:107:qemu user:/:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
# 第三栏是数字,但是这里并没有按数字大小来排序,因为默认使用文字排序
# 与数值大小进行排序
[root@k8s-node  ~]$ 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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

# 范例 3:利用 last ,将输出的数据仅取账户,并排序
[root@k8s-node  ~]$ last | cut -d ' ' -f 1 | sort

mrcode
mrcode

3.2 uniq命令:相同的行只显示其中一行

uniq命令参数:

  • i:忽略大小写
  • c:进行计数
# 范例 1: 使用 last 将账户列出,仅取出账户,排序后去重
[[root@k8s-node  ~]$ last | cut -d ' ' -f 1 | sort | uniq

mrcode
reboot
root
wtmp

# 范例 2:以上题,统计每个账户登录的总次数
[[root@k8s-node  ~]$ last | cut -d ' ' -f 1 | sort | uniq -c
      1
    136 mrcode
     19 reboot
      2 root
      1 wtmp

# 第一行和 wtmp 是 last 的默认字符,可以忽略

3.3 wc命令:计算文件里有多少字符、多少行?

wc命令参数:
-l:仅列出行
-w:仅列出多少字(英文单字)
-m:多少字符

# 范例 1:/etc/man_db.conf 这个文件里面有多少字
[root@k8s-node ~]$ cat  /etc/man_db.conf | wc
       行     字数       字符数
    131     723    5171

# 范例 2:last 可以输出登陆者,但是 last 最后两行并非账户内容,那么该如何以一行指令取得登录系统的总人次?
last | grep [a-zA-Z] | grep -v 'wtmp' | grep -v 'reboot' | grep -v 'unknown' | wc -l
138
# grep 正则匹配,排除了非英文字符的账户
# grep -v 反向选择,相当于排除了指定的账户
# 最后使用 wc 统计行数

原创文章,转载请注明出处:http://b.nwumba.cn/article/100/