文章目录

  • 前言
  • 一、grep
  • 命令语法
  • 实例
  • grep结合pattern正则
  • 二、sed
  • 命令语法
  • 案例
  • 三、awk
  • 命令语法
  • 实例


前言

最近看到了几篇关于linux命令grep、sed、awk的文章,这里总结下,方便后面使用。

一、grep

grep命令(grep的全称:Global search Regular Expression and Print out the line)主要用于文本内容的查找。它支持正则表达式查找。

命令语法

grep提供两种方式:

◆ grep [option] [pattern] testfile
#第一种是从文本中直接使用pattern匹配搜索
◆ stdout | grep [option] [pattern]
#第二种是从标准输出中处理 grep所提供的option(参数选项)

参数解释:

grep 第三列 grep保留第一行_grep


grep 第三列 grep保留第一行_grep 第三列_02

实例

做一个最简单的示例,如下先准备一个测试文件,内容如下:

grep 第三列 grep保留第一行_三剑客_03


从文本文件中搜索test字符串

grep 第三列 grep保留第一行_sed_04


可以看到包含有"test"的行被打印出来,默认grep是区分大小写的。所以"Test","TEST"没有被匹配出来。如果想要不区分大小写,我们可以加"-i"的参数。如下:

grep 第三列 grep保留第一行_sed_05

当前我们的测试文本内容比较少,我们肉眼可以见到是在第几行。如果文本行数较多的情况下那就不太方便了,这里就可以用到"-n"的参数

grep 第三列 grep保留第一行_三剑客_06


包含有"test"的并且不区分大小写的行在开头会显示行号,现在的结果中匹配的关键字所在行全部内容都会输出。如果只想要看到匹配的关键字,怎么办?使用"-o"参数即可

grep 第三列 grep保留第一行_三剑客_07

有时候我们需要对整个目录去搜索关键字,如果直接使用grep “test” 目录名,会报错。加参数’-r’就可以避免这个问题

grep 第三列 grep保留第一行_sed_08


可以看到shellTest目录下的两支文件test1.txt以及testfile都包含test被打印出来了“-q”选项表示使用静默模式,在此模式下grep命令不会有任何的打印结果,无论是否有匹配到。一般来说我们可以根据echo $?来查看上一条指令(grep)的执行结果,如果返回结果为0,表示grep有匹配到了,如果返回结果为1,表示grep没有匹配到。

grep 第三列 grep保留第一行_Linux命令_09


一般我们可以shell脚本中去用if条件分支进行判断,如果echo $?结果为0,就去执行相应的操作。

grep结合pattern正则

前面我们介绍了参数的基本用法,grep的强大之处其实是和正则表达式一起才有作用。

注:本篇文章不会具体介绍正则表达式的使用,如果不了解正则表达式的同学推荐去看下之前相关的文章
我们知道在正则表达式中分为了两类:

01 基本正则表达式

◆ . 单个字符
◆ * 表示前面的字符连续出现任意次,包括0次
◆ ^ 表示锚定行首
◆ $ 表示锚定行尾
◆ [a-z] [0-9] 区间范围
......

02 扩展正则表达式

◆ ?表示匹配其前面的字符0或1次
◆ + 表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
◆ () 分组
◆ {} 连续匹配
◆ | 匹配多个表达式的任何一个
......

如查询以"lemon"单词开头

grep 第三列 grep保留第一行_Linux命令_10


查找文件中空白行的数量

grep 第三列 grep保留第一行_grep 第三列_11

正则“^$”表示空白行,参数“-c”表达计算行数

连续字数的正则匹配,如:查找“appium”,p是连续的

grep 第三列 grep保留第一行_三剑客_12


“{2}”表示p连续出现了两次,可以发现结果是匹配不到的。因为{}是扩展正则表达式,grep默认是基本正则表达式,如果需要支持扩展正则表达式,我们需要加"-E"选项:

grep 第三列 grep保留第一行_Linux命令_13

二、sed

sed命令主要用于文本内容的编辑。默认只处理模式空间,不处理原数据,而且sed是针对一行行数据来进行处理的。Stream Editor文本流编辑,是一个"非交互式的"面向字符流的编辑器。

常用功能
(1) 、打印功能
能同时处理多个文件多行内容,可以不对原文件改动把整个文件输入到屏幕。
(2)、文本替换
把匹配到模式的内容输入到屏幕上。
(3)、修改文本
可以对原文件改动,但是不会在屏幕上返回结果。(谨慎使用!!!)

总结:
Sed就是修改文本、替换文本、打印文本的一个工具。

执行流程:

Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行…当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。如下,简单流程图。

grep 第三列 grep保留第一行_grep 第三列_14


补充:

一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。

例如:使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快。

命令语法

Sed [选项] 编辑命令 文件
Shell 命令 | sed [选项] 编辑命令

常用选项

-n:只显示匹配处理的行
-e:执行多个编辑命令(一般使用;代替)
-i:直接在文件中进行修改,不输出到屏幕
-r:支持扩展正则表达式
-f:从脚本文件中读取内容并执行文件中的编辑命令。
补充:这里比较常用的-n -r -e(用;代替)

常用编辑命令:

p:打印匹配行
d:删除匹配行
a:在定位行号后附加新文本信息
i:在定位行号后插入新文本信息
c:用新文本替换定位文本
r:从另一个文件中读文本,类似输入重定向(<)
w:写文本到一个文件,类似输出重定向(>)
s:使用替换模式替换相应模式
补充:这里比较常用的p d s

案例

案例1:
n 一般和 p连用
//打印文件的3-6行,使用行号

odysee:~$sed -n '3,6p' /etc/passwd

grep 第三列 grep保留第一行_grep 第三列_15


//打印(^odysee)以odysee开头的行,使用正则

sed -n '/^odysee/p' /etc/passwd

grep 第三列 grep保留第一行_sed_16

案例2:
参数d(删除匹配行),不会改变原文件内容
//$表示最后一行,!表示取反,d删除匹配行,p打印,;多个命令分割符
//连起来就是只打印文件最后一行

sed -n '$!d;p' /etc/passwd

grep 第三列 grep保留第一行_grep_17


查看原文件,并没有改变

grep 第三列 grep保留第一行_grep_18


案例3:

参数a(在定位行号后附加新文本信息)
//1a表示在第一行后面追加,也可使用正则

sed '1a abc' demo.txt

grep 第三列 grep保留第一行_三剑客_19


案例4:

参数i(在定位行号后插入新文本信息)
//1i:在第一行前插入,可以使用正则

sed '1i abc' demo.txt

grep 第三列 grep保留第一行_grep_20

三、awk

awk同sed命令类似,只不过sed擅长取行,awk命令擅长取列。(根据了解awk是一种语言,不过我们只关注他处理文本的功能,用的好的话几乎可以取代excel)
原理:一般是遍历一个文件中的每一行,然后分别对文件的每一行进行处理。
awk命令主要用于文本内容的分析处理。
如果对处理的数据需要生成报告之类的信息,或者处理的数据是按列进行处理的,最好使用awk。

命令语法

awk [可选的命令行选项] 'BEGIN{命令 } pattern{ 命令 } END{ 命令 }' 文件名

实例

打印某几列

$ echo 'I love you' | awk '{print $3 $2 $1}'
youloveI

我们将字符串 I love you 通过管道传递给awk命令,相当于awk处理一个文件,该文件的内容就是I love you,默认通过空格作为分隔符(不管列之间有多少个空格都将当作一个空格处理)I love you就分割成三列了。

假如分割符号为.,可以这样用

$ echo '192.168.1.1' | awk -F "." '{print $2}'
168

条件过滤

我们知道awk的用法是这样的,那么pattern部分怎么用呢?

awk [可选的命令行选项] 'BEGIN{命令 } pattern{ 命令 } END{ 命令 }' 文件名
$ cat score.txt
tom 60 60 60
kitty 90 95 87
jack 72 84 99
$ awk '$2>=90{print $0}' score.txt
kitty 90 95 87

$2>=90 表示如果当前行的第2列的值大于90则处理当前行,否则不处理。说白了pattern部分是用来从文件中筛选出需要处理的行进行处理的,这部分是空的代表全部处理。pattern部分可以是任何条件表达式的判断结果,例如>,<,==,>=,<=,!=同时还可以使用+,-,*,/运算与条件表达式相结合的复合表达式,逻辑 &&,||,!同样也可以使用进来。另外pattern部分还可以使用 /正则/ 选择需要处理的行。

判断语句

判断语句是写在pattern{ 命令 }命令中的,他具备条件过滤一样的作用,同时他也可以让输出更丰富

$ awk '{if($2>=90 )print $0}' score.txt
kitty 90 95 87
$ awk '{if($2>=90 )print $1,"优秀"; else print $1,"良好"}' score.txt
tom 良好
kitty 优秀
jack 良好

BEGIN 定义表头

awk [可选的命令行选项] 'BEGIN{命令 } pattern{ 命令 } END{ 命令 }' 文件名

使用方法如下:

$ awk 'BEGIN{print "姓名 语文 数学 英语"}{printf "%-8s%-5d%-5d%-5d\n",$1,$2,$3,$4}' score.txt
姓名 语文数学英语
tom 60 60 60
kitty 90 95 87
jack 72 84 99

这里要注意,我为了输出格式好看,做了左对齐的操作(%-8s左对齐,宽8位),printf用法和c++类似。

不仅可以用来定义表头,还可以做一些变量初始化的工作,例如

$ awk 'BEGIN{OFMT="%.2f";print 1.2567,12E-2}'
1.26 0.12

这里OFMT是个内置变量,初始化数字输出格式,保留小数点后两位。

END 添加结尾符

和BEGIN用法类似

$ echo ok | awk '{print $1}END{print "end"}'
ok
end

数据计算

这个地方我要放大招了!上面的知识点你都记住了吗?

$ awk 'BEGIN{print "姓名 语文 数学 英语 总成绩"; \
sum1=0;sum2=0;sum3=0;sumall=0} \
{printf "%5s%5d%5d%5d%5d\n",$1,$2,$3,$4,$2+$3+$4;\
sum1+=$2;sum2+=$3;sum3+=$4;sumall+=$2+$3+$4}\
END{printf "%5s%5d%5d%5d%5d\n","总成绩",sum1,sum2,sum3,sumall}'\
 score.txt
姓名 语文 数学 英语 总成绩
 tom 60 60 60 180
kitty 90 95 87 272
 jack 72 84 99 255
总成绩 222 239 246 707

因为命令太长,末尾我用\符号换行了。。

  • BEGIN体里我输出了表头,并给四个变量初始化0
  • pattern体里我输出了每一行,并累加运算
  • END体里我输出了总统计结果
  • 当然了,一个正常人在用linux命令的时候是不会输入那么多格式化符号来对齐的,所以新命令又来了
  • column -t(鬼知道我为什么会记得这么多乱七八糟的命令。)

    有用的内置变量

NF:表示当前行有多少个字段,因此$NF就代表最后一个字段
NR:表示当前处理的是第几行
FILENAME:当前文件名
OFMT:数字输出的格式,默认为%.6g。表示只打印小数点后6 位

$ awk -F ':' '{print NR ") " $1}' demo.txt
1) root
2) daemon
3) bin
4) sys
5) sync

内置函数

awk定义了很多内置函数,用awk来写shell脚本倒是一个不错的选择,但是大多数我们是用不上的,以下是常用函数

$ echo 1 2 | awk '{print $1+sqrt($2)}'
2.41421

随机数,先设置种子再随机

rand() 0 <= n < 1,srand([expr]) |将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。

$ echo 1 | awk 'BEGIN{srand()}{print rand()}'
0.929885

字符串

grep 第三列 grep保留第一行_sed_21

系统常用

grep 第三列 grep保留第一行_grep 第三列_22

不常用算数:

grep 第三列 grep保留第一行_grep 第三列_23