Linux三剑客(grep sed awk)

180 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情

grep

定义

根据用户指定的模式(pattern)对目标文本进行过滤,显示被模式匹配到的行

命令形式

grep [OPTIONS] PATTERN [FILES]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILES]
  • -v 显示不被pattern匹配到的行

  • -i 忽略字符大小写

  • -n 显示匹配的行号

  • -c 统计匹配的行数

  • -o 仅显示匹配到的字符串

  • -E 使用ERE,相当于egrep,使用扩展正则进行匹配,默认使用普通正则

实战一 文件内容检索

# 以/etc/passwd文件举例,可以先通过vim查看文件内容
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# vim /etc/passwd

# 1.不加任何参数,返回包含"root"的行
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

# 2.不加任何参数,返回以"root"开头的行
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

# 3.不加任何参数,返回以"n"结尾的行
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep n$ /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...

# 4."-v"参数,返回不包含"root"的行
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep -v root /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
......

# 5."-i"参数,忽略匹配字符的大小写
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep -i ROOT /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep ROOT /etc/passwd
无结果

# 6."-in"相当于"-i -n",忽略匹配自负的大小写,并且返回匹配行的行号
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep -in ROOT /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin

# 7."-on"相当于"-o -n",仅返回匹配的字符串,并且返回匹配字符串所在行的行号
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# grep -on root /etc/passwd
1:root
1:root
1:root
10:root

实战二 使用管道符串联命令

# 1.查看当前服务器占用的端口
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      18703/docker-proxy  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      5005/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      946/master          
tcp        0      0 0.0.0.0:2181            0.0.0.0:*               LISTEN      7602/docker-proxy   
tcp6       0      0 :::80                   :::*                    LISTEN      18707/docker-proxy  
tcp6       0      0 ::1:25                  :::*                    LISTEN      946/master          
tcp6       0      0 :::2181                 :::*                    LISTEN      7606/docker-proxy   
udp        0      0 0.0.0.0:68              0.0.0.0:*                           771/dhclient        
udp        0      0 127.0.0.1:323           0.0.0.0:*                           516/chronyd         
udp6       0      0 ::1:323                 :::*                                516/chronyd  

# 2.通常情况下上面端口会有很多记录,如果想要快速定位到某个端口被哪个服务占用,就可以使用管道符,将上一个命令的输出结果,做为下一个命令的输入
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# netstat -tunlp | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      18703/docker-proxy  
tcp6       0      0 :::80                   :::*                    LISTEN      18707/docker-proxy  

sed

定义

sed是流编辑器,一次处理一行内容,先将一行内容读取到模式空间,处理完成后输出到屏幕,然后清空模式空间,再次读入新的行,并没有直接修改源数据

命令形式

sed [-hn..][-e <script>][-f <script FILE>][FILE]
  • 基本参数

    • -h 显示帮组

    • -n 仅显示script处理后的结果

    • -i 替换源数据内容

  • 脚本参数

    • -e <script> 以选项中指定的script来处理输入的文本文件,不加-e会默认执行后面第一个非命令选项的参数
    • -f <script文件> 以选项中指定的script文件来处理输入的文本文件

脚本常用命令

指令说明示例说明
a新增sed -e '4 a newline'在第4行后,新增一行,内容为“newline”
c取代sed -e '2,5 c No 2-5 number'用c后面的内容取代2-5行的内容
d删除sed -e '2,5 d'删除2-5行
i插入sed -e '2 i newline'在第2行前,新增一行,内容为“newline”
p打印sed -n '/root/p'打印匹配root的内容 //之前的内容是正则表达式
s取代sed -e 's/old/new/g'用new替代old的内容 g全局 不加g只替换第一个匹配项

实战

# 先通过"vim"创建一个文件,填写内容,保存内容用于测试,可以通过"cat"命令查看文件内容
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# vim test.txt 
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# cat test.txt 
root admin root huyp
newn
root
new
root
snew
soon

# 1. 在第4行后新增一行,内容为"newline",通过"cat"命令可以查看并没有修改源内容
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# sed -e '4 a newline' test.txt 
root admin root huyp
newn
root
new
newline
root
snew
soon
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# cat test.txt 
root admin root huyp
newn
root
new
root
snew
soon

# 2. 通过"-i"参数,直接将结果更新到源文件中,通过"cat"命令查看文件内容(直接修改比较危险,可以先通过"-e"参数确认操作无误后再进行更新操作)
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# sed -i '4 a newline' test.txt 
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# cat test.txt 
root admin root huyp
newn
root
new
newline
root
snew
soon

awk

定义

以换行符为默认记录分隔符,逐一读取记录,以空格为默认域分隔符将每条记录切片,切开的部分再进行后续处理

命令形式

awk 'pattern + action' [FILE]
  • pattern 正则表达式,以/开头,以/结尾,缺省匹配所有;也可以是表达式,如NR==2打印第二行的内容,NR!=2打印除了第二行的所有内容

  • action 对匹配的内容执行的命令,缺省为输出内容 {print}

常用参数

  • FILENAME awk浏览的文件名
  • BEGIN 处理文本之前要执行的操作
  • END 处理文本之后要执行的操作
  • FS 设置输入域分隔符,等价于命令行-F选项,默认为空格
  • NF 浏览记录的域的个数(列数)
  • NR 已读的记录数(行数),通过【wc -l】命令可查询内容一共有多少行
  • OFS 输出域分隔符
  • ORS 输出记录分割符
  • RS 控制记录分隔符,默认为换行符
  • $0 整条记录
  • $1 表示当前行的第一个域....以此类推

实战

# 同样拿/etc/passwd文件来举例
# 1. 搜索/etc/passwd有root关键字的行,以":"为分隔符,并显示对应的shell(第7个字段)
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# awk '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# awk -F : '/root/ {print $7}' /etc/passwd
/bin/bash
/sbin/nologin


# 2.打印/etc/passwd的第二行信息
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# awk 'NR==2' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin

# 3.打印/etc/passwd的第二行及后面行的信息
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# awk 'NR>=2' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
......

# 使用begin先打印标题
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# awk -F : 'BEGIN{print "USER SHELL"}/root/ {print $1 $7}' /etc/passwd
USER SHELL
root/bin/bash
operator/sbin/nologin

综合实战

了解Docker的伙伴之后,如果想要删除所有已经停止的容器,只能通过命令docker rm container一个一个删除,如何通过一行命令将其全部删除呢?

# 1. 查看服务器上所有的容器,包括已经启动和未启动的
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS                        PORTS                                                                     NAMES
6af56a20ce03   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   About a minute ago   Exited (137) 31 seconds ago                                                                             app3
0eec70380901   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   About a minute ago   Exited (137) 44 seconds ago                                                                             app2
5fe2911d8cb4   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   About a minute ago   Exited (137) 58 seconds ago                                                                             app1
4520d2c79faa   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   4 days ago           Up 4 days                     0.0.0.0:80->5000/tcp, :::80->5000/tcp                                     app
50ecdf36dd1c   zookeeper             "/docker-entrypoint.…"   11 months ago        Up 5 days                     2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, :::2181->2181/tcp, 8080/tcp   zookeeper

# 2. 将上面的内容作为输入,通过"grep"查找出已经退出的容器
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# docker ps -a | grep Exited
6af56a20ce03   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   5 minutes ago   Exited (137) 4 minutes ago                                                                             app3
0eec70380901   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   5 minutes ago   Exited (137) 4 minutes ago                                                                             app2
5fe2911d8cb4   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   5 minutes ago   Exited (137) 4 minutes ago                                                                             app1
# 3. 将上面的内容作为输入,通过"awk"仅返回第一列容器ID字段
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# docker ps -a | grep Exited | awk '{print $1}'
6af56a20ce03
0eec70380901
5fe2911d8cb4

# 4. 再次将上面的内容作为输入,通过"docker rm container"命令删除容器,"xargs"将上一个命令的输入作为命令行参数
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# docker ps -a | grep Exited | awk '{print $1}' | xargs docker rm
6af56a20ce03
0eec70380901
5fe2911d8cb4

# 5.可以再次通过命令查看当前服务器上的所有容器(包括停止的),可以看到所有停止的容器全部被删除了
[root@iZwz95h9ihcvtbglpnnhx9Z ~]# docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS      PORTS                                                                     NAMES
4520d2c79faa   huyptina/hello:v1.1   "/bin/sh -c 'flask r…"   4 days ago      Up 4 days   0.0.0.0:80->5000/tcp, :::80->5000/tcp                                     app
50ecdf36dd1c   zookeeper             "/docker-entrypoint.…"   11 months ago   Up 5 days   2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, :::2181->2181/tcp, 8080/tcp   zookeeper
[root@iZwz95h9ihcvtbglpnnhx9Z ~]#