三剑客的功能非常强大,但我们只需要掌握他们分别擅长的领域即可: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,egrep
1)基本语法:grep + [options] pattern + file
分类 | |
基础正则 | ^ $ . * [a-z] |
扩展正则 | + | { } ? |
分类 | 用途 | 支持命令 |
正则(re) | 三剑客,高级语言,进行过滤(匹配字符) | 三剑客grep sed awk |
通配符 | 匹配文件(文件名)*.txt | Linux下面大部分命令 |
-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对文件实现快速增删改查,其中查询的功能中最常的两大功能是过滤、取行(取出指定行)。
1)基本语法:sed + [options] {sed - commmands} {input - file}
sed 选项 sed内置命令字符 输入文件
选项 | 解释 |
-n | 取消默认sed的输出,常与sed内置命令p一起使用 |
-i | 直接编辑原文件;直接将修改结果写入文件,不用-i,sed修改的是内部数据 |
-e | 多次编辑,不需要管道符 |
-r | 支持正则扩展 |
sed的内置命令字符用于对文件进行不同的操作功能,如对文件增删改查:
sed的内置命令字符 |
解释 |
a | append,对文本追加,在指定行后面添加一行/多行文本 |
d | delete,删除匹配行 |
i | insert,表示插入文本,在指定行前添加一行/多行文件 |
p | print,打印匹配的行,通常与-n一起用 |
s/正则/替换内容/g | 匹配正则内容,然后替换内容(支持正则),g代表全局匹配 |
范围 | 解释 |
空地址 | 全文处理 |
单地址 | 指定文件每一行 |
/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
命令 | 功能 |
c | replace 替代这行的内容 |
a | append 追加,向指定行追加内容(行后面) |
i | insert 插入,向指定的行插入内容(行前面) |
替换格式 |
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是一门编程语言,支持条件判断、数组、循环等功能。
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默认以空格为分隔符,且多个空格也识别为一个空格,作为分隔符。
内置变量 | 解释 |
$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
[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
[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默认是空格,空白字符,英文是filed separator ,变量名是FS
输出分隔符,output filed separator ,简称OFS
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正则 |
^表示以......开头的行 | 某一列的开头 |
$表示以.......结尾的行 | 某一列的结尾 |
^$表示空行 | 某一列是空的 |
例如:找到passwd中第四列以1开头的行
[root@zcf newdisk]# awk -F ':' '$4~/^1/' passwd.txt
模式 | 含义 | 应用场景 |
BEGIN{} | 里面的内容会在awk读取文件之前执行 | 1)进行简单统计,不涉及读取文件(常见) 2)用来处理文件之前,添加个表头 |
END{} | 里面的内容会在awk读取文件之后执行 | 1)awk进行统计,一般过程:先进行计算,最后END里面输出结果 2)awk使用数组,用来输出数组结果 |
统计方法:
统计方法 | 简写方式 | 应用场景 |
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}'
统计日志:
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
#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}}'
统计磁盘空间使用率:
[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