一、grep:文本过滤工具
grep 语法格式:
grep [OPTIONS] PATTERN [FIFE]
grep 参数 匹配模式 查找的文件
参数选项 | 解释说明 |
---|---|
-v | 显示不匹配的行,或者说排除某些行,显示不包含匹配文本的所有行 |
-n | 显示匹配行及行号 |
-i | 不区分大小写(只适用于单字符),默认是区分大小写的 |
-c | 只统计匹配的行数,注意不是匹配的次数 |
-E | 使用扩展的 egrep 命令 |
--color=auto | 为 grep 过滤的匹配字符串添加颜色 |
-w | 只匹配过滤的单词,单词的两边必须是非字符符号(即不能是字母数字或下划线) |
-o | 只输出匹配的内容 |
有文本如下(test.txt)
test
dongye
oldboy
linux
ubuntu
centos
LOL
dota2
i like playing dota2
1.1 -v 参数实践
# 过滤不包含oldboy字符串的行,注意被过滤的字符串,尽可能使用双引号
grep -v "dota2" test.txt
>>>
test
dongye
oldboy
linux
ubuntu
centos
LOL
提示:
grep 的 -v 参数的作用是排除,默认是以行为单位排除包含参数后面所接内容的某些行
1.2 -n 参数实践
# 输出包含 oldboy 字符串的行,并显示行号
grep -n "dota2" test.txt
>>>
1:dota2
2:i like playing dota2
提示:
-n 参数会对 grep 命令找到的内容在开头加上对应的行号
1.3 -i 不区分大小写参数实践
grep "lol" test.txt
>>>
找不到值
grep -i "lol" test.txt
>>>
LOL
1.4 -E 和 --color 的参数实践
# 默认不支持多条件匹配
grep "like|dota2" test.txt
# 多条件匹配,加 -E
grep -E "like|dota2" test.txt
>>>
dota2
i like playing dota2
# 加颜色
grep -Ei --color=auto "like|dota2" test.txt
1.5 -c 参数实践
grep "dota2" test.txt
>>>
dota2
i like playing dota2
# 只想计算匹配的字符串的数量
grep -c "dota2" test.txt
>>>
2
1.6 -o 参数实践
# 注意这里没有 双引号
grep -o dota2 test.txt
>>>
dota2
dota2
1.7 -w 参数实践
grep -w "like" text.txt
# 结果为空
1.8 grep 常用
# 查找指定进程
ps -ef | grep nginx
# 查找指定进程并统计数量
ps -ef | grep -c nginx
# 从文件中查找关键字
grep 关键字 test.txt
# 从文件中查找关键字并输出它的行号
grep -n 关键字 text.txt
# 从多个文件中查找关键字
grep 关键字 test1.txt test2.txt test3.txt
# 从文件中查找关键字后,再从结果中找到指定关键字
cat text.txt | grep -v 不要的关键字 | grep -w 要的单词
ps -ef | grep dub-finance | grep -v grep | awk '{print $2}' | xargs kill -9
# 找出文件中的空白行
grep -n "^$" test.txt
# 显示当前目录下面以 .txt 结尾的文件中的所有包含每个字符串至少有4个连续小写字符的字符串的行
grep -n '[a-z]{4}' *.txt
二、sed:字符流编辑器
语法格式
sed [选项] [sed内置命令字符] [输入文件]
说明:
- sed以及后面的选项、命令和输入文件,每个元素之间都至少要有一个空格。
- 【sed内置命令字符】,既可以是单个命令,也可以是多个命令参数的组合
- 【输入文件】为sed 需要处理的文件,这是可选项,sed 还能够从标准输入如管道中获取输入
2.1 选项、内置命令说明
参数选项
参数选项 | 解释说明 |
---|---|
-n | 取消默认的sed的输出,常与sed内置命令的p连用 |
-i | 直接修改文件内容,而不是输出到终端。如果不使用 -i 选项,则sed只是修改内存中的数据,并不会影响磁盘上的文件 |
sed内置命令字符
sed的内置命令字符 | 解释说明 |
---|---|
a | 全拼 append,表示追加文本,在指定行后添加一行或多行文本 |
d | 全拼 delete,表示删除匹配行的文本 |
i | 全拼 insert,表示插入文本,在指定行前添加一行或多行文本 |
p | 全拼 print,表示打印匹配行的内容,通常 p 会与选项 -n 一起使用 |
s/regexp/replacement | 匹配 regexp 部分的内容,用 replacement 替换 regexp 匹配的内容,regexp部分可以使用正则表达式,在 replacement 部分可以使用特殊字符 & 和 1-9等匹配 regexp 部分的部分内容。在实战场景中,s/regexp/replacement/g 结尾常与g匹配做全局的替换 |
2.2 示例文本
先准备一个文本 tex.txt
101,oldboy,CEO
102,zhangyao,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
2.3 在文本指定行后追加文本
sed "2a 106,dandan,CSO" test.txt
>>>
101,oldboy,CEO
102,zhangyao,CTO
106,dandan,CSO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
2a 106,dandan,CSO
的意思:
- 2 表示对第 2 行进行操作,其他的行忽略
- a 表示追加,2a 即在第 2 行后追加文本
- 2a 后面加上空格,然后接着输入想要追加的文本内容(106,dandan,CSO`)即可
2.4 在文本指定的行前面插入文本
sed "2i 106,dandan,CSO" text.txt
>>>
101,oldboy,CEO
106,dandan,CSO
102,zhangyao,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
2i 106,dandan,CSO
的意思:
- 2 表示对第 2 行进行操作,其他的行可忽略
- i 代表插入的意思,2i 表示在第2行即当前行插入文本,即插入到第二行
- 2i 后面加上空格,然后跟上要插入的文本(106,dandan,CSO),最后接上要处理的文件 text.txt
2.5 在文件指定行后追加多行文本
sed "2a 106,dandan,CSO
107,bingbing,CCO" text.txt
>>>
101,oldboy,CEO
102,zhangyao,CTO
106,dandan,CSO
107,bingbing,CCO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
2.6 删除文件中一行指定的文本
sed "2d" text.txt
>>>
101,oldboy,CEO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
2.7 删除文件中指定的多行文本
sed "2,5d" text.txt
# 表示删除 2-5 行,所以结果只剩下一行
>>>
101,oldboy,CEO
2.8 使用sed命令替换文本内容
sed "s#zhangyao#dandan#g" text.txt
>>>
101,oldboy,CEO
102,dandan,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
2.9 打印输出文件的指定行的内容
sed "2p" text.txt
# 这里使用了 sed 内置命令 p 来实现查询功能,并结合数字地址指定查询第2行的内容,但是我们会发现结果不只是输出第2行,文件的其他内容也显示出来了,这是因为 sed 命令有一个默认输出的功能.
>>>
101,oldboy,CEO
102,zhangyao,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CTO
sed -n "2p" text.txt
# 为了解决上面命令显示多余内容的问题,使用选项 -n 取消默认输出,只输出匹配行的文本,因此大家只需要记住使用命令 p 必用选项 -n
>>>
102,zhangyao,CTO
sed -n "2,4p" text.txt
# 输出 2-4 行
>>>
102,zhangyao,CTO
103,Alex,COO
104,yy,CFO
2.10 -i 选项
这个选项的作用是能够实际修改文件的内容,前面几个例子操作完命令之后,文件的内容并没有发生变化,这是因为 sed 命令默认操作的是内存中的数据,如果想要真正地修改文件的内容,就需要使用选项 `-i`将修改写到磁盘文件上。
2.11 N 内置命令
有文件如下
stu10309
7f754wdw
stu10123
faioj322
stu12452
fasdassa
...
现在要把格式变成
stu10309=7f754wdw
stu10123=faioj322
stu12452=fasdassa
可用以下方法实现
sed "N;s#
#=#g" text.txt
sed 内置命令 N 的作用:不会清空模式空间的内容,并且从输入文件中读取下一行数据,追加到模式空间中,两行数据以换行符
连接。
第一行是 `stu10309` 存入模式控件,碰到命令 `N`,读取第二行 `7f754wdw`,此时模式空间的内容为 `stu10309
7f754wdw`;然后执行 `s#
#=#g` 将 `
`替换为 `=`,即为 `stu10312=`7f754wdw`,输出到屏幕中,第一个循环结束;后面的循环和前面的思路一样,直到文件结束。
三、awk 基础入门
不仅是Linux系统中的一个命令,而且还是一种编程语言。是Linux系统最强大的文本处理工具,没有之一。
3.1 参数选项及说明
awk 命令的常用功能 | 简要例子说明 |
---|---|
指定分隔符显示某几列 | awk -F "GET|HTTP" '{print $2}' test.log 直接取出显示出日志文件的 url 这一列 |
通过正则表达式取出你想要的的内容 | awk '$6~/Failed/{print $11}' /var/log/secure 分析生产环境中的日志找出谁在破解用户的密码 |
显示出某个范围内的内容 | awk 'NR20,NR30' filename 显示文件的20到30行内容 |
通过awk进行统计计算 | awk '{sum+=$0}END{print sum}' ett.txt 计算总和 |
awk数组计算与去重 | awk '{array[$1]++}END{for(key in array)print key,array[key]}' access.log 对日志进行统计与计数 |
awk [option] 'pattern{action}' file ...
参数 '条件{动作}' 文件 ...
参数选项及说明
参数选项 | 解释说明 |
---|---|
-F | 指定字段分隔符 |
-v | 定义或修改一个 awk 内部的变量 |
3.2 示例文本
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/mologin
adm:x:3:4:adm:/var/adm:/sbin/lologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool?mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
3.3 显示文件中的第5行
cat -n test.txt # 先打印内容并在每行内容的开头显示行号
awk 'NR==5' test.txt
首先NR 在awk中表示行号(记录号),NR==5表示行号等于5的行。这里需要注意的是必须使用两个等号,在awk中两个等号表示 ”等于“,一个等号表示赋值,即向一个变量里面放置内容。
注意:awk后面所接的内容要用单引号
显示一部分行的内容,例如显示 2-6 行
awk 'NR==2,NR==6' test.txt
3.4 用 awk 实现给文件每行的内容之前加上行号
awk '{print NR,$0}' test.txt
这里的NR还是表示行号,$0 表示一整行的内容(一行的内容)。
3.5 显示第 2 行到 第 6 行,并打印行号
awk 'NR==2,NR==6 {print NR,$0}' test.txt
3.6 显示文件的第 1 列、第 3 列和最后一列
awk -F ":" '{print $1,$3,$NF}' test.txt
这里我们使用了 awk 的 -F参数。-F表示指定一个`分隔符`来切割每一行的内容,-F后面可用单双引号或不加引号,但是,建议加双引号。
`$1`表示根据分隔符分割的第一列,`$2`表示根据分隔符分割的第二列,以此类推。
`$0`表示整行。`$NF`表示最后一列。
3.7 把文件中的 /sbin/nologin 替换为 /bin/bash
awk '{gsub("/sbin/nologin","/bin/bash",$0);print $0}' test.txt
3.8 生产案例1:取出 eh0 网卡对应的ip地址
ifconfig eth0
>>>
eho Link encap:Ethernet Hwaddr 00:0C:29:93:49:99
inet addr:10.0.0.8 Bcast:10.0.0.255 Mask:255.255.255.0
...
取出的方式
ifconfig eth0|awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}'
>>>
10.0.0.8
我们的目标是取得ip,本例是10.0.0.8,ip的左边是 addr:
,右边是 Bcast:
。所以两边都是分隔符,就可以取到我们想要取到的值。(这里需要注意-F 指定多分割符的写法
)
还有一个简单的方法
ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
结合起来,-F "[ :]+"
就是以单个或连续的空格或冒号或者它们的组合为分隔符。最后就可以获得我们想要的ip地址。
3.9 面试题--统计域名访问次数
测试数据如下:
http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html
3.9.1 方案1
(1)取出每行中的域名
awk -F '/' '{print $3}' test.txt
>>>
www.etiantian.org
www.etiantian.org
post.etiantian.org
mp3.etiantian.org
www.etiantian.org
post.etiantian.org
(2)排序(让相同的域名相邻)
awk -F '/' '{print $3}' test.txt|sort
(3)去重计数
awk -F '/' '{print $3}' test.txt|sort|uniq -c
3.9.2 方案2(awk数组方案)
(1)取出域名
awk -F '/' '{print $3}' test.txt
(2)创建一个 awk 数组,然后把第二列(域名)作为数组的下标,再通过类似于 i++ 的形式来计算域名重复的次数
awk -F '/' '{hotel[$3]}' test.txt # 创建 awk 的hotel 数组
awk -F '/' '{hotel[$3];print $3}' test.txt #创建 awk 的hotel 数组,并通过 print 输出元素名字(房间号码),注意,这里没输出数组,所以看到的还是第一阶段的内容
>>>
awk -F '/' '{print $3}' test.txt
(3)开始统计
awk -F '/' '{hotel[$3]++;print $3,hotel[$3]}' test.txt
>>>
www.etiantian.org 1
www.etiantian.org 2
post.etiantian.org 1
mp3.etiantian.org 1
www.etiantian.org 3
post.etiantian.org 2
(4)输出最终结果
上面的命令详细地显示了 awk 统计的过程。如果想要获得最终结果该怎么办呢?通过END模式来输出最终结果。
awk -F '/' '{array[$3]++}END{
print "www.etiantain.org",array["www.etiantian.org"];
print "post.etiantian.org",array["post.etiantian.org"];
print "mp3.etiantian.org",array["mp3.etiantian.org"];
}' test.txt
awk数组提供了自己独有的方法来完成它——一个专用的循环:
awk -F '/' '{hotel[$3]++}END{for(domain in hotel)print damain,hotel[domain]}' test.txt
>>>
mp3.etiantian.org 1
post.etiantian.org 2
www.etiantian.org 3