28.文本处理三剑客grep,sed,awk

三剑客的功能非常强大,但我们只需要掌握他们分别擅长的领域即可:grep擅长查找功能,sed擅长取行和替换,awk擅长取列。

目录

一、grep

二、sed

sed选项

sed内置常用命令字符

sed匹配范围

例子:测试文件

sed 增加 c a i

 sed替换 s

练习:

三、awk

awk内置变量  

一次性输出多列:

自定义输出内容:

显示文件第五行:

显示文件2-5行

给每一行的内容添加行号

显示文件3-5行输出行号:

显示文件的第一列,倒数第二和最后一列:

awk分隔符

FS输入分隔符

awk模式匹配--正则匹配

特殊模式BEGIN{}和END{}

END{}统计计算

例子:

awk数组

awk for循环

awk if判断


一、grep

文本过滤工具,grep,egrep

1)基本语法:grep + [options] pattern + file

分类
基础正则^   $  .  *  [a-z]
扩展正则+ | { } ?

正则VS通配符

分类用途支持命令
正则(re)三剑客,高级语言,进行过滤(匹配字符)

三剑客grep sed awk

通配符匹配文件(文件名)*.txtLinux下面大部分命令

-v:显示不能被模式匹配到的行,即反向过滤。

-i :忽略字符的大小写。

-o :仅显示匹配到的字符串本身。

-w :匹配整个单词

-E :支持扩展正则=egrep

遇到(){} ?+ | 就要开启扩展正则

-A #  : 后#行

-B# :前#行

-C# :前后各#行

grep例子:

1.显示/etc/passwd文件中不以/bin/bash结尾的行:

[root@zcf ~]# grep -v '/bin/bash$' /etc/passwd

2.找出/etc/passwd文件中的两位数或三位数:

[root@zcf ~]# egrep -w '[0-9]{2,3}' /etc/passwd

3.找出/etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行:

 egrep '^[[:space:]]+[^[:space:]]' /etc/grub2.cfg

4.找出‘netstat -tan’命令的结果中以‘LISTEN’后跟0,1或多个空白字符结尾的行:

[root@zcf ~]# netstat -tan | grep 'LISTEN[[:space:]]*$'

5.找出/proc/meminfo文件中以大小写s开头的行,至少三种方式:

[root@zcf ~]# grep -i '^s' /proc/meminfo
[root@zcf ~]# grep  '^[sS]' /proc/meminfo
[root@zcf ~]# egrep  '^(s|S)' /proc/meminfo

6.显示当前系统上root,centos,user1用户的信息:

[root@zcf ~]# egrep '^(root|centos|user1)\>' /etc/passwd

二、sed

sed对文件实现快速增删改查,其中查询的功能中最常的两大功能是过滤、取行(取出指定行)。

1)基本语法:sed + [options] {sed - commmands} {input - file}

                        sed            选项        sed内置命令字符     输入文件

sed选项

选项解释
-n取消默认sed的输出,常与sed内置命令p一起使用
-i直接编辑原文件;直接将修改结果写入文件,不用-i,sed修改的是内部数据
-e 多次编辑,不需要管道符
-r支持正则扩展

sed的内置命令字符用于对文件进行不同的操作功能,如对文件增删改查:

sed内置常用命令字符

sed的内置命令字符

解释
aappend,对文本追加,在指定行后面添加一行/多行文本
ddelete,删除匹配行
iinsert,表示插入文本,在指定行前添加一行/多行文件
pprint,打印匹配的行,通常与-n一起用
s/正则/替换内容/g匹配正则内容,然后替换内容(支持正则),g代表全局匹配

sed匹配范围

范围解释
空地址全文处理
单地址指定文件每一行
/pattern/被模式匹配到的每一行
范围区间

10,20    10到20行

10,+5    第10行向下5行

步长

1~2,表示1,3,5,7

2~2,表示2,4,6,8

例子:测试文件

[root@zcf newdisk]# cat sed.txt
northwest       NW      Charles Main    4.0     .99     3       35
western         WE      Sharon Gray     8.3     .97     5       23
southwest       SW      Lewis Dalsass   4.7     .8      2       19
southern        SO      Suan Chin       5.1     .96     4       15
southeast       SE      Patric Hemenway 4.0     .7      4       16
eastern         EA      TB savage       7.7     .84     5       22
northeast       NE      AM Main Jr.     5.1     .96     3       13
north           No      Margot WEber    3.4     .87     5       8
central         CT      Ann Stephens    2.7     .94     5       14

1.默认情况,sed把所有输入行都打印在标准输出上。如果匹配某一行north,sed就把这一行另外打一遍:

[root@zcf newdisk]# sed '/north/p' sed.txt
northwest       NW      Charles Main    4.0     .99     3       35
northwest       NW      Charles Main    4.0     .99     3       35
western         WE      Sharon Gray     8.3     .97     5       23
southwest       SW      Lewis Dalsass   4.7     .8      2       19
southern        SO      Suan Chin       5.1     .96     4       15
southeast       SE      Patric Hemenway 4.0     .7      4       16
eastern         EA      TB savage       7.7     .84     5       22
northeast       NE      AM Main Jr.     5.1     .96     3       13
northeast       NE      AM Main Jr.     5.1     .96     3       13
north           No      Margot WEber    3.4     .87     5       8
north           No      Margot WEber    3.4     .87     5       8
central         CT      Ann Stephens    2.7     .94     5       14

# -n,只打印处理过的:

[root@zcf newdisk]# sed -n '/north/p' sed.txt
northwest       NW      Charles Main    4.0     .99     3       35
northeast       NE      AM Main Jr.     5.1     .96     3       13
north           No      Margot WEber    3.4     .87     5       8

2.命令d用于删除输入行。sed先将输入行从文件复制到模式缓存区,然后对该执行 sed命令。最后将模式缓存区的内容显示在屏幕上。如果发出的是命令 d ,当前模式缓存区的输入行会被删除,不被显示:

[root@zcf newdisk]# sed '3d' sed.txt
northwest       NW      Charles Main    4.0     .99     3       35
western         WE      Sharon Gray     8.3     .97     5       23
southern        SO      Suan Chin       5.1     .96     4       15
southeast       SE      Patric Hemenway 4.0     .7      4       16
eastern         EA      TB savage       7.7     .84     5       22
northeast       NE      AM Main Jr.     5.1     .96     3       13
north           No      Margot WEber    3.4     .87     5       8
central         CT      Ann Stephens    2.7     .94     5       14

# 删除从第三行到最后一行,剩下各行被打印,地址范围是从第3行到最后一行:   

[root@zcf newdisk]# sed '3,$d' sed.txt
northwest       NW      Charles Main    4.0     .99     3       35
western         WE      Sharon Gray     8.3     .97     5       23

   # 使用地址定界,模式匹配到的行:

[root@zcf newdisk]# sed '/north/d' sed.txt
western         WE      Sharon Gray     8.3     .97     5       23
southwest       SW      Lewis Dalsass   4.7     .8      2       19
southern        SO      Suan Chin       5.1     .96     4       15
southeast       SE      Patric Hemenway 4.0     .7      4       16
eastern         EA      TB savage       7.7     .84     5       22
central         CT      Ann Stephens    2.7     .94     5       14

3.命令s是替换命令。替换和取代文件中的文本可以通过sed 中的s来实现,g代表全局匹配

[root@zcf newdisk]# sed 's/north/south/g' sed.txt
southwest       NW      Charles Main    4.0     .99     3       35
western         WE      Sharon Gray     8.3     .97     5       23
southwest       SW      Lewis Dalsass   4.7     .8      2       19
southern        SO      Suan Chin       5.1     .96     4       15
southeast       SE      Patric Hemenway 4.0     .7      4       16
eastern         EA      TB savage       7.7     .84     5       22
southeast       NE      AM Main Jr.     5.1     .96     3       13
south           No      Margot WEber    3.4     .87     5       8
central         CT      Ann Stephens    2.7     .94     5       14

# s 命令用于替代。选项 -n 与命令行末尾的标志p 结合,只打印发生替换的行:

[root@zcf newdisk]# sed -n 's/north/south/gp' sed.txt
southwest       NW      Charles Main    4.0     .99     3       35
southeast       NE      AM Main Jr.     5.1     .96     3       13
south           No      Margot WEber    3.4     .87     5       8

4. 正则表达式&

# 当 ”与“ 符号(&)用于替换串中时,他代表在查找串中匹配到的内容。

[root@zcf newdisk]# sed -r 's/[0-9]{2}$/&.1/' sed.txt
northwest       NW      Charles Main    4.0     .99     3       35.1
western         WE      Sharon Gray     8.3     .97     5       23.1
southwest       SW      Lewis Dalsass   4.7     .8      2       19.1
southern        SO      Suan Chin       5.1     .96     4       15.1
southeast       SE      Patric Hemenway 4.0     .7      4       16.1
eastern         EA      TB savage       7.7     .84     5       22.1
northeast       NE      AM Main Jr.     5.1     .96     3       13.1
north           No      Margot WEber    3.4     .87     5       8
central         CT      Ann Stephens    2.7     .94     5       14.1

5.多重编辑,可以指定多个编辑动作:

[root@zcf newdisk]# sed -e '1,3d' -e 's/south/north/' sed.txt
northern        SO      Suan Chin       5.1     .96     4       15
northeast       SE      Patric Hemenway 4.0     .7      4       16
eastern         EA      TB savage       7.7     .84     5       22
northeast       NE      AM Main Jr.     5.1     .96     3       13
north           No      Margot WEber    3.4     .87     5       8
central         CT      Ann Stephens    2.7     .94     5       14

6.sed 增加 c a i

命令功能
creplace 替代这行的内容
aappend 追加,向指定行追加内容(行后面)
iinsert 插入,向指定的行插入内容(行前面)

7. sed替换 s

替换格式
s###g
s///g
s@@@g

s:替换

g: 全局替换,sed替换所有匹配的,sed默认只替换每行第一个匹配的内容

7.后向引用,反向引用

口诀:先保护,在使用

练习:

1)ip a 通过反向引用取ens33ip:

[root@zcf ~]# ip a show ens33 |sed -n '3p' |sed -r 's#^.* (.*)/.*$#\1#g'
192.168.150.129

2)sata / 取权限555


[root@zcf ~]# stat / |sed -rn '4s#^.*\(0(.*)/d.*$#\1#gp'
555

三、awk

awk是一门编程语言,支持条件判断、数组、循环等功能。

1)基本语法:awk + [option]    'pattern [action]'  file

                              awk可选参数   模式 动作       文件

action指的是动作,awk擅长文本格式化,且输出格式化后的结果,因此最常用的动作就是print

# options:

-F :定义输入字段分隔符,默认的分隔符是空格或制表符(tab)

-v :定义或修改一个awk内部的变量

-f : 从脚本文件中读取awk命令        

# command:

BEGIN{}                        {}                                END{}

行处理前                    行处理                          行处理后

我们执行的命令是awk ‘{print $2}’ ,没有使用参数和模式,$2表示输出文本的第二列信息。

awk默认以空格为分隔符,且多个空格也识别为一个空格,作为分隔符。

  • $0表示整行
  • $NF表示当前分割后的最后一列
  • 倒数第二列也可以写成$(NF-1)

awk内置变量  

内置变量解释

$n

指定分隔符后,当前记录的第n个字段
$0完整的输入记录
FS字段分隔符,默认是空格
NF(Number of filelds)分割后,当前行一共有多少个字段
NR(Number of records)当前记录数,行数

一次性输出多列:

[root@zcf newdisk]# awk '{print $1,$2}' sed.txt
northwest NW
western WE
southwest SW
southern SO
southeast SE
eastern EA
northeast NE
north No
central CT

自定义输出内容:

awk,必须外层单引号,内层双引号

内置变量 $1 $2 ,都不得添加双引号,否则会识别为文本,尽量别加引号

[root@zcf newdisk]# awk '{print "第一列",$1,"第二列",$2}' sed.txt
第一列 northwest 第二列 NW
第一列 western 第二列 WE
第一列 southwest 第二列 SW
第一列 southern 第二列 SO
第一列 southeast 第二列 SE
第一列 eastern 第二列 EA
第一列 northeast 第二列 NE
第一列 north 第二列 No
第一列 central 第二列 CT

显示文件第五行:

#NR在wak表示行号,NR==5表示行号是5的那一行

#注意一个等于号,是修改变量值的意思,两个等于号是关系运算符,是‘等于’的意思

[root@zcf newdisk]# awk 'NR==5' sed.txt
southeast       SE      Patric Hemenway 4.0     .7      4       16

显示文件2-5行

[root@zcf newdisk]# awk 'NR==2,NR==5' sed.txt
western         WE      Sharon Gray     8.3     .97     5       23
southwest       SW      Lewis Dalsass   4.7     .8      2       19
southern        SO      Suan Chin       5.1     .96     4       15
southeast       SE      Patric Hemenway 4.0     .7      4       16

给每一行的内容添加行号

添加变量,NR等于行号,$0表示一整行的内容

{print}是awk的动作

[root@zcf newdisk]# awk '{print NR,$0}' sed.txt
1 northwest     NW      Charles Main    4.0     .99     3       35
2 western               WE      Sharon Gray     8.3     .97     5       23
3 southwest     SW      Lewis Dalsass   4.7     .8      2       19
4 southern      SO      Suan Chin       5.1     .96     4       15
5 southeast     SE      Patric Hemenway 4.0     .7      4       16
6 eastern               EA      TB savage       7.7     .84     5       22
7 northeast     NE      AM Main Jr.     5.1     .96     3       13
8 north         No      Margot WEber    3.4     .87     5       8
9 central               CT      Ann Stephens    2.7     .94     5       14

显示文件3-5行输出行号:


[root@zcf newdisk]# awk 'NR==3,NR==5{print NR,$0}' sed.txt
3 southwest     SW      Lewis Dalsass   4.7     .8      2       19
4 southern      SO      Suan Chin       5.1     .96     4       15
5 southeast     SE      Patric Hemenway 4.0     .7      4       16

显示文件的第一列,倒数第二和最后一列:


[root@zcf newdisk]# awk '{print $1,$(NF-1),$NF}' sed.txt
northwest 3 35
western 5 23
southwest 2 19
southern 4 15
southeast 4 16
eastern 5 22
northeast 3 13
north 5 8
central 5 14

awk分隔符

输入分隔符,awk默认是空格,空白字符,英文是filed separator ,变量名是FS

输出分隔符,output filed separator ,简称OFS

FS输入分隔符

awk逐行处理文本的时候,以输入分隔符为准,把文本切成多个片段,默认符号是空格

当我们处理特殊文件,没有空格的时候,可以自由指定分隔符特点

[root@zcf newdisk]# awk -F ':' '{print $1}' passwd.txt
zcf
zwj
mom
tom
jack
group1
rose
mariadb
nash
bob
alice
john
steve
david
snake

除了使用-F选项,还可以使用变量的形式,指定分隔符,使用-v 选项搭配,修改FS变量

[root@zcf newdisk]# awk -v FS=":" '{print $1}' passwd.txt
zcf
zwj
mom
tom
jack
group1
rose
mariadb
nash
bob
alice
john
steve
david
snake

OFS输出分隔符

awk执行完命令,默认用空格隔开每一列,这个空格就是awk的默认输出符:

[root@zcf newdisk]# awk -v OFS='-----' '{print $1,$NF}' sed.txt
northwest-----35
western-----23
southwest-----19
southern-----15
southeast-----16
eastern-----22
northeast-----13
north-----8
central-----14

awk模式匹配--正则匹配

/ / :里面支持扩展正则

awk可以精确到某一列,某一列中包含或不包含

~ 包含

!~不包含

正则awk正则
^表示以......开头的行某一列的开头
$表示以.......结尾的行某一列的结尾
^$表示空行某一列是空的

例如:找到passwd中第四列以1开头的行

[root@zcf newdisk]# awk -F ':' '$4~/^1/' passwd.txt

特殊模式BEGIN{}和END{}

模式含义应用场景
BEGIN{}里面的内容会在awk读取文件之前执行

1)进行简单统计,不涉及读取文件(常见)

2)用来处理文件之前,添加个表头

END{}里面的内容会在awk读取文件之后执行

1)awk进行统计,一般过程:先进行计算,最后END里面输出结果

2)awk使用数组,用来输出数组结果

END{}统计计算

统计方法:

统计方法简写方式应用场景
i++i=i+1计数,统计次数
sum=sum+???sum+=???求和,累加
注意:i,sum都是变量

例子:

统计/etc/services空行数目:

[root@zcf ~]# awk '/^$/{i++}END{print i}' /etc/services
17

 seq 100 求和1+2+3+...+100 awk实现:

[root@zcf ~]# seq 100 |awk '{sum=sum+$0}END{print sum}'
5050

如果想看过程:

[root@zcf ~]# seq 100 |awk '{sum=sum+$1;print sum}END{print sum}'

awk数组

统计日志:

  • 统计次数:类似于统计每个ip出现次数,统计每种状态码出现的次数,统计系统每个用户被攻击的次数,统计攻击者ip出现次数,
  • 累加求和:统计每个ip消耗的流量
shell数组awk数组
形式

a[0]=grep

a[1]=sed

a[0]=grep

a[1]=sed

使用

echo ${a[0]} ${a[1]}

print a[0] a[1]
批量输出数组内容

for i in ${a[*]}

do

     echo $i

done

for(i in a)

     print a[i]

awk数组专用循环,变量获取到的是数组的下标,你想要数组内容   a[ i ]

例子:

[root@zcf ~]# awk 'BEGIN{a[0]="grep";a[1]="sed"; print a[0],a[1]}'
grep sed
[root@zcf ~]# awk 'BEGIN{a[0]="grep";a[1]="sed"; for(i in a) print i}'          0
1
[root@zcf ~]# awk 'BEGIN{a[0]="grep";a[1]="sed"; for(i in a) print a[i]}'
grep
sed

处理以下文件内容,将域名取出来并统计排序处理:
httpd://www.etiantian.org/index.html
httpd://www.etiantian.org/1.html
httpd://post.etiantian.org/index.html
httpd://mp3.etiantian.org/index.html
httpd://www.etiantian.org/3.html
httpd://post.etiantian.org/2.html

[root@zcf newdisk]# awk -F '[//]+' '{array[$2]++}END{for(i in array) print i,array[i]}' url.txt
mp3.etiantian.org 1
www.etiantian.org 3
post.etiantian.org 2

 ##array[ ]++ 你要统计什么 [ ]里面就是什么(某一列)

统计access.log中IP 出现次数 array[$1]++

[root@zcf logs]# awk '{array[$1]++}END{for (i in array)print i,array[i]}' access_log
192.168.150.129 8
192.168.150.1 127

awk for循环

#1+...+100

[root@zcf logs]# awk 'BEGIN{for(i=1;i<=100;i++) sum+=i; print sum}'
5050

##显示过程:

[root@zcf logs]# awk 'BEGIN{for(i=1;i<=100;i++) {sum+=i; print sum}}'

awk if判断

统计磁盘空间使用率:

[root@zcf logs]# df -h | awk -F "[ %]+" 'NR>1{if($5>1)print "disk not enough"}' disk not enough
disk not enough
disk not enough
disk not enough
disk not enough

统计这段语句中,单词中字符数小于6的单词显示出来:

echo I am oldboy teacher welcome to oldboy training class。

[root@zcf ~]# echo I am oldboy teacher welcome to oldboy training class |awk '{for(i=1;i<=NF;i++) if(length($i)<6) print $i}'
I
am
to
class

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值