【Linux】(16)文本处理命令:管道+awk+xargs+tr+sort+uniq+cut

目录

一、管道 |

1.1 管道的用处

1.2 【拓展】进程与进程之间的通信方式

1.2.1 管道 pipe

        1.2.2 socket文件

        1.3 【拓展】awk 截取

        1.4 ; 命令连接符、

        1.5 插入两个小练习

        1.5.1

        1.5.2

        1.5.3 【知识补充】如何判断一个目录是否存在

        1.5.4 在python中如何判断文件夹是否存在

        1.6 xargs

二、文本处理命令

        2.1 tr命令

        2.1.1 tr命令的一个注意事项

        2.1.2 替换文件里的某一些内容

        2.1.3 选项(-d -s)

        2.2 sort

        2.2.1 默认情况

        2.2.2 指定排序键 -k

        2.2.3 指定分割符 -t

        2.2.4 综合性例题

        2.3 uniq

        2.3.1 【例】搭建一个nginx的web服务器,统计访问次数最多的前3个ip地址

        2.4 cut

        2.4.1 常见选项

        2.4.2 提取范围

三、插入一个练习


一、管道 |

将前面命令的输出送给后面的命令使用

1.1 管道的用处

默认情况下,管道只会将前面一个命令正确的输出送给后面一个命令作为输入。

[root@localhost 0325]# ip add | grep "inet"
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 192.168.255.132/24 brd 192.168.255.255 scope global noprefixroute dynamic ens33
    inet6 fe80::5e3f:2e7b:4978:aa4e/64 scope link noprefixroute
[root@localhost 0325]# ip fdlihua | grep "fd"
Object "fdlihua" is unknown, try "ip help".

【实现将错误的输出也传给后面的命令】

grep 是一个文本过滤命令,根据字符串去匹配,只要这一行里含有这个字符串就会输出这一行。

[root@localhost 0325]# ip fdlihua 2>&1 | grep "fd"
Object "fdlihua" is unknown, try "ip help".

1.2 【拓展】进程与进程之间的通信方式

1.2.1 管道 pipe

默认情况下,为了保护进程安全,进程和进程之间是不能随意访问。

管道文件作为一个中间文件,存放在内存里,默认只接受上一个命令正确的输出。


[root@localhost 0325]# find / -type "p"     ==》在根目录下查找管道类型的文件
/run/dmeventd-client
/run/dmeventd-server
/run/systemd/inhibit/1.ref
/run/systemd/sessions/3704.ref
/run/systemd/sessions/3703.ref
/run/systemd/sessions/2029.ref
/run/systemd/sessions/4.ref
/run/systemd/initctl/fifo
[root@localhost 0325]# ll /run/systemd/initctl/fifo
prw-------. 1 root root 0 3月  23 12:47 /run/systemd/initctl/fifo

        1.2.2 socket文件

socket文件可以是存放在磁盘里的

【Linux】(16)文本处理命令:管道+awk+xargs+tr+sort+uniq+cut_第1张图片

 

        1.3 【拓展】awk 截取

【shell编程里文本处理3剑客】

  1. grep:过滤
  2. awk:截取:行里的字段,一个字段代表一列
  3. sed:替换

awk 是截取的命令

'{ }' 是固定的语法,用来输出内容

$0 代表整行

$1 代表第1个字段

$2 代表第2个字段

-F 指定分割符。awk 默认的字段和字段之间的分割符是空白(空格、ab)

, 是表示输出的时候使用一个空格作为分割符

NF 是awk里的一个变量 代表一行里有多少个字段(字段的数量)number of fields

$NF 表示最后一列

[root@localhost 0324]# cat student_info.txt
name    age     sex     grade
cali    36      m       80
lihua   18      m       90
hanmei  25      f       85
liyu    22      f       93
[root@localhost 0324]# cat student_info.txt | awk '{print $4}'
grade
80
90
85
93
[root@localhost 0324]# cat student_info.txt | awk '{print $1,$4}'
name grade
cali 80
lihua 90
hanmei 85
liyu 93

        1.4 ; 命令连接符、

可以将多个命令写到一行,不管前面的命令是否执行成功,都会执行所有命令

cmd1 ; cmd2 ; cmd3 先执行cmd1,再执行cmd2,再执行cmd3

[root@localhost 0325]# cd dfhw ; echo hello ; cat sadfhs
-bash: cd: dfhw: 没有那个文件或目录
hello
cat: sadfhs: 没有那个文件或目录

cmd1 && cmd2 如果cmd1执行成功就执行cmd2,如果cmd1执行不成功就不执行cmd2

cmd1 || cmd2 如果cmd1执行不成功,就执行cmd2,如果cmd1执行成功就不执行cmd2

cmd1 && cmd2 || cmd3 如果cmd1执行成功,就执行cmd2,如果执行不成功就执行cmd3

[root@localhost 0325]# echo 1 && echo 2 || echo 3
1
2
[root@localhost 0325]# cat 1 && echo 2 || echo 3
cat: 1: 没有那个文件或目录
3

以上3个命令,不要和if语句的条件弄混了

        1.5 插入两个小练习

        1.5.1

【Linux】(16)文本处理命令:管道+awk+xargs+tr+sort+uniq+cut_第2张图片

 【答案】EGHI

[root@localhost 0325]# cat aa bb | cat
aaaaaa
bbbbbbbbbbbb
[root@localhost 0325]# cat < aa; cat < bb
aaaaaa
bbbbbbbbbbbb
[root@localhost 0325]# cat aa bb > /dev/stdout
aaaaaa
bbbbbbbbbbbb
[root@localhost 0325]# cat aa bb > /dev/stderr
aaaaaa
bbbbbbbbbbbb

        1.5.2

【Linux】(16)文本处理命令:管道+awk+xargs+tr+sort+uniq+cut_第3张图片

 

# 第一题
id feng &>/dev/null && echo 123456|passwd feng --stdin
# 第二题
==如何判断一个目录是否存在
1. cd
2. ls
3. stat
4. find
5. [ -d /backup ]   ==>[ -d 目录地址 ]
==答案
[ -d /backup ] || mkdir /backup 或者  mkdir /backup -p
# 第三题
du -sh / 2>/dev/null

        1.5.3 【知识补充】如何判断一个目录是否存在

  1. cd
  2. ls
  3. stat
  4. find
  5. [ -d /backup ] test -d /backup 两种方式等价,命令的效果也相同,只是语法不同

【注意】中括号里两侧一定要有空格

-d 判断是否是目录 directory

-f 判断是否是文件 file

-e 判断文件或文件夹是否存在 exist

        1.5.4 在python中如何判断文件夹是否存在

 判断:os.path.exists() 新建:os.mkdir()

>>> import os
>>> os.path.exists("/backup")
False
>>> os.mkdir("/backup")
>>> os.path.exists("/backup")
True

【脚本】

[root@localhost 0325]# vim dir.py

[root@localhost 0325]# cat dir.py 
#!/usr/bin/python3

import os

if os.path.exists("/backup"):
	print("/backup is exists")
else:
	os.mkdir("/backup")
	print("/backup create ok")
[root@localhost 0325]# python3 dir.py 
/backup is exists
[root@localhost 0325]# rm -rf /backup
[root@localhost 0325]# python3 dir.py 
/backup create ok
[root@localhost 0325]# ls /
backup

        1.6 xargs

将前面命令的输出送给后面的命令作为参数使用

用途:将参数列表转换成小块分段传递给其他命令

读入stdin的数据转换为参数添加到命令行中

让一些不支持管道的命令可以使用管道。

【注】xargs需要依赖管道,只是将前面的命令的输出送给后面的命令做参数使用,更加精准

[root@localhost 0325]# which mkdir
/usr/bin/mkdir
[root@localhost 0325]# which mkdir | ls -l  ==》管道符号将输出送来,ls -l不知道如何使用,就没有用
总用量 8
-rw-r--r--. 1 root root 144 3月  25 13:29 dir.py
-rw-r--r--. 1 root root 210 3月  25 09:58 position.py

[root@localhost 0325]# ls -l
总用量 8
-rw-r--r--. 1 root root 144 3月  25 13:29 dir.py
-rw-r--r--. 1 root root 210 3月  25 09:58 position.py

如何实现以下效果

[root@localhost 0325]# ls -l /usr/bin/mkdir
-rwxr-xr-x. 1 root root 79768 8月  20 2019 /usr/bin/mkdir

【通过xargs】

[root@localhost 0325]# which mkdir | xargs ls -l
-rwxr-xr-x. 1 root root 79768 8月  20 2019 /usr/bin/mkdir

二、文本处理命令

        2.1 tr命令

tr - translate or delete characters

tr 是字符转换和删除字符的工具

tr set1 set2 意为:用set2中的字符替换掉set1中同一位置的字符

# 将所有的1都替换为a,所有的2都替换为b,所有的3都替换为b,
[root@localhost 0325]# echo 123456112233445566 | tr 123 abc
abc456aabbcc445566
[root@localhost 0325]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost 0325]# echo $PATH | tr ":"  "\n"   ==》将所有的:替换为换行
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
[root@localhost 0325]# echo $PATH | tr ":"  " "  ==》将所有的:替换为空格
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /root/bin

        2.1.1 tr命令的一个注意事项

只能对stdin操作,不能直接对文件操作

需要使用管道或者< 给tr传递参数

[root@localhost 0325]# cat name
chunhuofanmingyou
chunhuofanmingyou
chunhuofanmingyou
chunhuofanmingyou
chunhuofanmingyou
chunhuofanmingyou
[root@localhost 0325]# tr "c" "C" name
tr: 额外的操作数 "name"
Try 'tr --help' for more information.
[root@localhost 0325]# tr "c" "C" < name
Chunhuofanmingyou
Chunhuofanmingyou
Chunhuofanmingyou
Chunhuofanmingyou
Chunhuofanmingyou
Chunhuofanmingyou

[root@localhost 0325]# cat name |tr "f" "F"
chunhuoFanmingyou
chunhuoFanmingyou
chunhuoFanmingyou
chunhuoFanmingyou
chunhuoFanmingyou
chunhuoFanmingyou

        2.1.2 替换文件里的某一些内容

【Linux】(16)文本处理命令:管道+awk+xargs+tr+sort+uniq+cut_第4张图片 [0-9.] 等价于 [0123456789.]

[root@localhost 0325]# cat name 
1.1chunhuofanmingyou
1.2chunhuofanmingyou
1.3chunhuofanmingyou
1.4chunhuofanmingyou
1.5chunhuofanmingyou
1.6chunhuofanmingyou
[root@localhost 0325]# cat name | tr '[0-9]' ' '  ==》删除文件中的数字
 . chunhuofanmingyou
 . chunhuofanmingyou
 . chunhuofanmingyou
 . chunhuofanmingyou
 . chunhuofanmingyou
 . chunhuofanmingyou
[root@localhost 0325]# cat name | tr '[0-9.]' ' '  ==》删除文件中的数字和.
   chunhuofanmingyou
   chunhuofanmingyou
   chunhuofanmingyou
   chunhuofanmingyou
   chunhuofanmingyou
   chunhuofanmingyou

        2.1.3 选项(-d -s)

-d 删除字符串

-s 压缩相同的字符串(将连续相同的字符压缩成一个字符) 去重

[root@localhost 0325]# echo 1345464321343543 | tr -d 3
14546421454
[root@localhost 0325]# echo 12111234533333333322 | tr -s 123
121234532

        2.2 sort

一个排序命令,默认分隔符是空白

默认按每一行的第一个字符排序 ==》按照行首第一个字符的ASCII码值升序(从小到大)排列

-n 按整数进行排序 number ==》将一串数字识别成一个整数

        【举例】22 和 203

        【解释】如果不接-n,默认是先比较第一位(2和2)==》相同,再比较第二位(2和0)==》前一个更大==》22>203

                        接了-n,就会比较整体比较22和203==》得到203>22

[root@localhost 0325]# cat test.txt | sort
203
22
[root@localhost 0325]# cat test.txt | sort -n
22
203

-r 递减排序 reverse

# python里二进制、字符和ASCII码的转换
>>> bin(99)
'0b1100011'   ==》0b开头的就是二进制数
>>> chr(97)
'a'
>>> ord('a')
97
[root@localhost 0325]# cat student_info.txt 
name    age    sex    Chinese    Math    English
cali    36     M      80         75      76
fmy     3      M      60         87      79
fzt     19     F      83         92      75
nyx     26     F      92         85      86

        2.2.1 默认情况

按照行首第一个字符的ASCII码值升序(从小到大)排列。如果首字母相同,就同理比较第2个字符

[root@localhost 0325]# cat student_info.txt |sort
cali    36     M      80         75      76
fmy     3      M      60         87      79
fzt     19     F      83         92      75
name    age    sex    Chinese    Math    English
nyx     26     F      92         85      86

        2.2.2 指定排序键 -k

指定按哪一列数据进行排序,默认是升序

[root@localhost 0325]# cat student_info.txt |sort -k4
fmy     3      M      60         87      79
cali    36     M      80         75      76
fzt     19     F      83         92      75
nyx     26     F      92         85      86
name    age    sex    Chinese    Math    English
[root@localhost 0325]# cat student_info.txt |sort -k4 -n 
name    age    sex    Chinese    Math    English
fmy     3      M      60         87      79
cali    36     M      80         75      76
fzt     19     F      83         92      75
nyx     26     F      92         85      86
[root@localhost 0325]# cat student_info.txt |sort -k4 -nr
nyx     26     F      92         85      86
fzt     19     F      83         92      75
cali    36     M      80         75      76
fmy     3      M      60         87      79
name    age    sex    Chinese    Math    English

        2.2.3 指定分割符 -t

【举例】

 

[root@localhost 0325]# cat /etc/passwd | sort -n -k 3 -t : -r
lihua321:x:1012:1012::/home/lihua321:/bin/bash
shijunhao:x:1011:1011::/home/shijunhao:/bin/bash
liangluyao:x:1010:1010::/home/liangluyao:/bin/bash
xiaohong:x:1009:1009::/home/xiaohong:/bin/bash

        2.2.4 综合性例题

[root@localhost 0325]# ps aux | sort -k4 -rn | head -5
root        715  0.0  1.5 359024 29168 ?        Ssl  3月24   0:03 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid
root       1076  0.0  0.9 574280 17456 ?        Ssl  3月24   0:08 /usr/bin/python2 -Es /usr/sbin/tuned -l -P
polkitd     682  0.0  0.6 613004 13012 ?        Ssl  3月24   0:05 /usr/lib/polkit-1/polkitd --no-debug
root        754  0.0  0.5 700304  9536 ?        Ssl  3月24   0:08 /usr/sbin/NetworkManager --no-daemon
root      72201  0.0  0.3 158904  5608 ?        Ss   13:08   0:00 sshd: root@pts/1
[root@localhost 0325]# ps aux | sort -k3 -rn | head

[root@localhost 0325]# ps aux | sort -k4 -rn | head -5|awk '{print $2,$4,$11}'
715 1.5 /usr/bin/python2
1076 0.9 /usr/bin/python2
682 0.6 /usr/lib/polkit-1/polkitd
754 0.5 /usr/sbin/NetworkManager
72201 0.3 sshd:

        2.3 uniq

去重(连续重复的多行数据只显示一行)==》一定要先使用sort的行,让重复的内容连在一起

-c 统计重复的次数 count

-u 只显示唯一的行

-d 显示重复的行

[root@localhost 0325]# cat student_info.txt 
name    age    sex    Chinese    Math    English
cali    36     M      80         75      76
fmy     3      M      60         87      79
fzt     19     F      83         92      75
nyx     26     F      92         85      86
[root@localhost 0325]# cat student_info.txt |awk '{print $3}'
sex
M
M
F
F
[root@localhost 0325]# cat student_info.txt |awk '{print $3}'|sort
F
F
M
M
sex
[root@localhost 0325]# cat student_info.txt |awk '{print $3}'|sort|uniq
F
M
sex
[root@localhost 0325]# cat student_info.txt |awk '{print $3}'|sort|uniq -c
      2 F
      2 M
      1 sex
[root@localhost 0325]# cat student_info.txt |awk '{print $3}'|sort|uniq -u
sex
[root@localhost 0325]# cat student_info.txt |awk '{print $3}'|sort|uniq -d
F
M

        2.3.1 【例】搭建一个nginx的web服务器,统计访问次数最多的前3个ip地址

【步骤】

        第一步:安装nginx web服务器软件==》yum install nginx -y

        第二步:启动nginx服务==》service nginx restart

        第三步:关闭防火墙==》service firewalld stop

                查看防火墙的规则

[root@localhost 0325]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   

        第四步:查看ip地址==》ip add

        第五步:打开浏览器输入ip地址,访问你的web服务器

                [root@localhost nginx]# curl http://192.168.255.132 ==》Linux里访问

        第六步:修改网站的首页

[root@localhost 0325]# cd /usr/share/nginx/html   进入nginx服务存放网页的目录
[root@localhost html]# ls
404.html  en-US  img           index.html      poweredby.png
50x.html  icons  IMG_7438.JPG  nginx-logo.png

        index.html 网站看到的第一个界面==》首页

        echo "hello, world" > index.html 替换修改index.html里面的内容

        第七步:刷新刚刚在浏览器打开的网页,会看到我们自己重定向进去的内容

        第八步:进入记录nginx日志的目录

[root@localhost html]# cd /var/log/nginx
[root@localhost nginx]# ls
access.log  access.log-20211222  error.log  error.log-20211222

access.log 访问日志,记录谁什么时间访问了那个界面,成功还是失败

[root@localhost nginx]# cat access.log | tail -1
192.168.255.1 - - [25/Mar/2022:17:07:54 +0800] "GET /IMG_7438.JPG HTTP/1.1" 304 0 "http://192.168.255.132/" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" "-"

192.168.255.1 表示哪台客户机访问量我们的web服务

[25/Mar/2022:17:07:54 +0800] 访问时间

【答案】统计得出访问量前3的ip地址

[root@localhost nginx]# cat access.log | awk '{print $1}'|sort|uniq -c|sort -rn|head -3|awk '{print $2}'

        2.4 cut

截取文本的命令

默认分割符是tab

从文本文件或者文本流中提取文本列

【格式】cut -选项 提取范围 文本文件

        2.4.1 常见选项

-c 从指定提取范围中提取字符(单个字符)[root@localhost 0325]# echo 123456|cut -c 2 得到==》 2

-f 从指定提取范围中提取字段(列) fields

-d 指定分隔符

[root@localhost 0325]# cat student_info.txt |cut -f 1  ==》因为默认的分割符是tab键
name    age    sex    Chinese    Math    English
cali    36     M      80         75      76
fmy     3      M      60         87      79
fzt     19     F      83         92      75
nyx     26     F      92         85      86
[root@localhost 0325]# cat student_info.txt |cut -d " " -f 1
name
cali
fmy
fzt
nyx

【注】有时候会无法截取:因为它认为连续的两个分割符之间也算一个字段,需要和tr结合,可去除多余的内容,保证没有连续的分割符

[root@localhost 0325]# echo 1#2#3#4##5|cut -d "#" -f 5   ==》无法截取:因为它认为#和#之间也算一个字段

[root@localhost 0325]# echo 1#2#3#4##5|cut -d "#" -f 6
5
[root@localhost 0325]# w
 17:42:03 up 1 day,  2:43,  3 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      三12    2days  0.05s  0.05s -bash
root     tty2                      四09    7:57m  0.04s  0.04s -bash
root     pts/1    192.168.255.1    13:08    3.00s  0.36s  0.00s w
[root@localhost 0325]# w|cut -d " " -f 1,2  ==》同理无法切割
 17:42:06
USER 
root 
root 
root 
[root@localhost 0325]# w|tr -s " " |cut -d " " -f 1,2  ==》和tr结合,可去除多余的空格
 17:42:24
USER TTY
root tty1
root tty2
root pts/1

        2.4.2 提取范围

类似于python中的切片

        n 第n项

        n- 第n向到行尾

        -m 行首到第m项

        n,m 第n项和第m项 :单个的

        n-m 第n项到第m项:连续的

[root@localhost 0325]# echo 123456|cut -c 2
2
[root@localhost 0325]# echo 123456|cut -c 2-4
234
[root@localhost 0325]# echo 123456|cut -c 1,3,5
135

三、插入一个练习

【Linux】(16)文本处理命令:管道+awk+xargs+tr+sort+uniq+cut_第5张图片 grep 过滤命令,输出含有匹配的字符串所在的行

        选项:-o 只是输出匹配到的内容,不匹配不显示

# 第一题
==答案1
[root@localhost ~]# ll -R | sort -n -k5
==答案2
[root@localhost ~]# ll -R | sort -n -k5 | awk '{print $5,$9}'
# 第二题
[root@localhost ~]# cat /etc/passwd | cut -d ":" -f 7 | sort |uniq -c
[root@localhost ~]# cat /etc/passwd | awk -F: '{print $7}'|sort |uniq -c
# 第三题
==答案1
[root@localhost ~]# df -Th | awk '{print $1,$2,$6}'
==答案2
[root@localhost ~]# df -Th |tr -s " " |cut -d " " -f 1,2,6
# 第四题
==答案1
[root@localhost ~]# cat /etc/passwd|tr ":" "\n" | grep sbin|awk -F '/' '{print $2}'|uniq -c
==答案2 
[root@localhost ~]# cat /etc/passwd|tr ":" "\n" | grep sbin|wc -l
==答案3
[root@localhost ~]# cat /etc/passwd|grep -o sbin|wc -l
==答案4
[root@localhost ~]# cat /etc/passwd|grep -o sbin|uniq -c
# 第五题
[root@localhost ~]# ps aux | sort -nr -k 4|head -5
# 第六题
[root@localhost ~]# ps aux | sort -nr -k 3|head -5
# 第七题

[root@localhost ~]# ip add | grep "192"
# 第八题
[root@localhost nginx]# cat access.log|awk '{print $1}' | sort |uniq -c|sort -nr|head -3
# 第九题
[root@localhost nginx]# cat access.log|awk '{print $9}' | sort |uniq -c|sort -nr|head -2

你可能感兴趣的:(Linux,linux,运维,服务器,经验分享)