首先,我们想了解Linux三剑客具体是什么?
grep
,grep在每个文件中或匹配的每一行进行pattern模式,即根据正则表达式搜索内容并打印出来awk
,awk由三个作者名字缩写(Aho, Kernighan, Weinberger),它可以根据定位到的数据行处理其中的分段。sed
,它是stream editor编辑器简介,根据输入内容作出过滤的文本能力,对过滤数据进行增删改查操作。它们三个组合来使用,可以应对Shell中的很多数据分析场景,所以人们都把这三个工具统称为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,我们接下来看如何具体的使用它们。
我们先创建一个文件,文件内包括三条数据,后文以该文件内容作为演示操作
#方式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
grep
用于根据正则表达式模式查找相关内容并打印对应数据。
hogwarts
单词是否在文件中rosaany@Rosefinch:~$ grep hogwarts test.txt hello from hogwarts # 匹配到hogwarts单词,输出一整行
rosaany@Rosefinch:~$ grep '^he' test.txt hello from hogwarts hello from sevenriby hello from testerhome
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 # --------加入\转义符对匹配条件进行转移,也可以达到同样的效果。
awk
是一种语言解析引擎,它的功能非常强大,具备完整的编程特性,可以执行命令、进行网络请求等操作。
接下来看下 awk 的语法 awk 'pattern{action}'
的相关知识,pattern 是匹配条件,action 表示具体需要做的处理。
rosaany@Rosefinch:~$ awk "/(seven|home)/" test.txt hello from sevenriby hello from testerhome
pettern 语法在一定程度上可以代替 grep,但没有使用grep简洁
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|
rosaany@Rosefinch:~$ awk 'BEGIN{print 10/3}' 3.33333
除了这些之外,awk 还支持词典,用来统计一些特征和数据,它类似于 Java 的 hash 和 Python 的字典。awk 的语法非常灵活,希望你在课后能够把文档打印出来仔细阅读,它可以帮助你在日后的数据分析工作中更加得心应手。
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
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
可以根据匹配的数据进行分组处理管道符|
,在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
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文档详解