1.Linux三剑客是什么
首先,我们想了解Linux三剑客具体是什么?
- 第一个工具是
grep
,grep在每个文件中或匹配的每一行进行pattern模式,即根据正则表达式搜索内容并打印出来 - 第二个工具是
awk
,awk由三个作者名字缩写(Aho, Kernighan, Weinberger),它可以根据定位到的数据行处理其中的分段。 - 第三个工具是
sed
,它是stream editor编辑器简介,根据输入内容作出过滤的文本能力,对过滤数据进行增删改查操作。
它们三个组合来使用,可以应对Shell中的很多数据分析场景,所以人们都把这三个工具统称为Linux三剑客。
2.Linux三剑客有什么用
接下来,通过对三剑客与SQL进行类比,来具体看看它们到底能做什么?
-
grep
相当于SQL的select * from table
,它可以进行数据的查找与定位。 -
awk
相当于SQL的select columns from table
,它可以进行数据的切片。 -
sed
相当于SQL的select columns from table where columns=xx
,update table set columns=new where columns=old
,它可以进行数据的条件查询或修改等
你可以发现,grep 和 awk 可以进行组合使用,来达到查找数据并对数据进行分割的目的,grep 也可以与 sed 组合使用,达到查找数据并修改的目的,它们三个还可以组合在一起使用来完成一系列的操作,就相当于大数据处理中的 Map-Reduce,我们接下来看如何具体的使用它们。
3.Linux三剑客具体怎么用
我们先创建一个文件,文件内包括三条数据,后文以该文件内容作为演示操作
#方式1: vim test.txt(在当前目录下新建一个文件,输入如下三条数据)
hello from hogwarts
hello from sevenriby
hello from testerhome
# 方式2:使用echo命令输入,其中-e参数表示开启转义符的解释功能
echo -e 'hello from hogwarts\nhello from sevenriby\nhello from te
sterhome' > test.txt
# -------------------------查看-------------------------
#rosaany@Rosefinch:~$ cat test.txt
#hello from hogwarts
#hello from sevenriby
#hello from testerhome
3.1 grep
grep
用于根据正则表达式模式查找相关内容并打印对应数据。
- 查找
hogwarts
单词是否在文件中
rosaany@Rosefinch:~$ grep hogwarts test.txt
hello from hogwarts
# 匹配到hogwarts单词,输出一整行
- 查找以hello开头的单词是否在文件中
rosaany@Rosefinch:~$ grep '^he' test.txt
hello from hogwarts
hello from sevenriby
hello from testerhome
- 查找包含i或y字母的单词是否在文件中
rosaany@Rosefinch:~$ grep '[iy]' test.txt
hello from sevenriby
- 加入
-v
参数过滤掉匹配到的内容
rosaany@Rosefinch:~$ grep -v '[iy]' test.txt
hello from hogwarts
hello from testerhome
-
-o
参数表示只打印匹配的数据
rosaany@Rosefinch:~$ grep -o '[iy]' test.txt
i
y
-E
参数表示支持使用扩展正则表达式
grep这里的(pattern模式)正则表达式分为两类,第一类称为基本表达式,基本表达式包括了典型的正则标识符。
-
^
表示开头; -
$
表示结尾; -
[]
表示任意匹配项; -
*
表示0个或多个; -
.
表示任意字符
第二类是扩展表达式,它在基础表达式上做了一些扩展,支持更高级的语法和更复杂的条件。
-
?
表示非贪婪匹配; -
+
表示一个或多个; -
()
表示分组; -
{}
表示一个范围的约束; -
|
表示匹配多个表达式的任何一个
- 加入
-E
参数,查找一个包括seven或home单词是否在文件中
rosaany@Rosefinch:~$ grep -E "(seven|home)" test.txt
hello from sevenriby
hello from testerhome
- 不加入
-E
参数,查找一个包括seven或home单词是否在文件中
rosaany@Rosefinch:~$ grep "\(seven\|home\)" test.txt
hello from sevenriby
hello from testerhome
# --------加入\转义符对匹配条件进行转移,也可以达到同样的效果。
3.2 awk
awk
是一种语言解析引擎,它的功能非常强大,具备完整的编程特性,可以执行命令、进行网络请求等操作。
接下来看下 awk 的语法 awk 'pattern{action}'
的相关知识,pattern 是匹配条件,action 表示具体需要做的处理。
- 使用双/表示一个正则匹配,效果如同前面的grep一样
rosaany@Rosefinch:~$ awk "/(seven|home)/" test.txt
hello from sevenriby
hello from testerhome
pettern 语法在一定程度上可以代替 grep,但没有使用grep简洁
- 查找第3行数据
rosaany@Rosefinch:~$ awk 'NR>=3' test.txt
hello from testerhome
# NR参数代表记录数
pattern有非常丰富的语法,你可以课后自己进行练习,同时 awk 还有几个标准的内置变量。
-
FS
表示字段分隔符 -
OFS
表示输出数据的字段分隔符 -
RS
表示记录分隔符` -
ORS
表示输出字段的行分隔符 -
NF
表示字段数 -
NR
表示记录数
- 查找文件记录数与字段数
rosaany@Rosefinch:~$ awk '{print NR,NF}' test.txt
1 3
2 3
3 3
# 默认空格作为分隔符,分别输出第一行有3个字段,第二行有3个字段,第三个有3个字段
- 查找文件记录数与字段数(指定分隔符
o
,使用-F
参数指定)
rosaany@Rosefinch:~$ awk -Fo '{print NR,NF,$1,$2,$3,$4}' test.txt
1 4 hell fr m h gwarts
2 3 hell fr m sevenriby
3 4 hell fr m testerh me
# $1~$n输出对应的记录
- 也可以使用
BEGIN
指令分隔符
rosaany@Rosefinch:~$ awk 'BEGIN{FS="o"}{print NR,NF,$1,$2,$3,$4}' test.txt
1 4 hell fr m h gwarts
2 3 hell fr m sevenriby
3 4 hell fr m testerh me
# FS变量指定分隔符
- 输出数据指定字段分隔符
|
rosaany@Rosefinch:~$ awk 'BEGIN{OFS="|"}{print NR,NF,$1,$2,$3,$4}'test.txt
1|3|hello|from|hogwarts|
2|3|hello|from|sevenriby|
3|3|hello|from|testerhome|
- 输出数据指定字段分隔符
|
,OFS直接指定
rosaany@Rosefinch:~$ awk 'OFS="|"{print NR,NF,$1,$2,$3,$4}' test.txt
1|3|hello|from|hogwarts|
2|3|hello|from|sevenriby|
3|3|hello|from|testerhome|
- awk还支持简单的运算功能
rosaany@Rosefinch:~$ awk 'BEGIN{print 10/3}'
3.33333
除了这些之外,awk 还支持词典,用来统计一些特征和数据,它类似于 Java 的 hash 和 Python 的字典。awk 的语法非常灵活,希望你在课后能够把文档打印出来仔细阅读,它可以帮助你在日后的数据分析工作中更加得心应手。
3.3 sed
sed
的具体常用法如下:
-
sed[addr]X[options]
,其中 [] 定义了一个范围,x位是具体操作,options表示进行数据修改的选项。 -
-e
表示可以指定表达式。 -
sed -n '2p' 2
表示打印第二行的数据 -
s
表示查找并替换 -
-i
表示直接修改源文件 -
-E
支持扩展表达式。
- 使用
s
查找前面的内容并替换为后面内容
rosaany@Rosefinch:~$ sed 's#test#testing#' test.txt
hello from hogwarts
hello from sevenriby
hello from testingerhome
# ‘#’或‘/’都可以表示分隔符
# testerhome 变为 testingerhome
- 以t开头的三个字符替换成xxx
rosaany@Rosefinch:~$ sed 's/t../xxx/g' test.txt
hello from hogwarts
hello from sevenriby
hello from xxxxxxhome
# s/../../g表示全局替换
# testerhome 变为 xxxxxxhome
如果你想给定具体的行数或范围通过正则匹配作替换修改
rosaany@Rosefinch:~$ sed '3,$ s/t../xxx/g' test.txt # 直接指定范围($表示到最后一行)
hello from hogwarts
hello from sevenriby
hello from xxxxxxhome
- 删除指定行
rosaany@Rosefinch:~$ sed '1 d' test.txt
hello from sevenriby
hello from testerhome
awk
更专注于数据的提取,而sed
更专注于数据的修改,sed的重要作用是完成对数据的增删改查工作,比如:
-
d
是删除 -
p
是打印 -
s
是查找并进行替换 -
\1 \2
可以根据匹配的数据进行分组处理
4. 管道组合
管道符|
,在shell中表示将上一个指令的输出自动变成下一个指令的输入。
- 给定具体的行数或范围通过正则匹配作替换修改
rosaany@Rosefinch:~$ awk 'NF<2' test.txt | sed 's/t../xxx/g'
rosaany@Rosefinch:~$ awk 'NF>2' test.txt | sed 's/t../xxx/g'
hello from hogwarts
hello from sevenriby
hello from xxxxxxhome
- grep、awk、sed的结合
rosaany@Rosefinch:~$ cat test.txt | grep hogwarts | awk '{print $3}' | sed 's/h../xxx/g'
# -----------------输出-----------------
xxxwarts
# 输入cat命令指定输出文件,接着grep只保留hogwarts所在的行,接着awk打印处第三个字段,最后sed把h开头的三个字符替换为xxx。
通过管道我们很容易让Linux三剑客的功能发挥到一个新高度,有了管道很多的操作就变得非常的简单容易处理。通过管道于三剑客相结合使用可以实现非常好的效果,它可以帮助我们处理一些复杂的数据处理工作,提高我们的工作效率。
参考文章
部分引用:测试开发核心技术 46 讲 -- Linux三剑客,来自:拉勾教育
参考:man sed, man grep, man awk文档详解