“grep, sed, awk”这三个命令非常常用,素有“Linux三剑客”之称,本篇就来讲讲这三个命令,其中grep用来查找特定格式字符串,sed擅长取行分析,awk擅长取列分析。
1. grep
grep命令比较简单,常用来进行文本过滤,它的基本格式为:
grep [options] pattern input
其中pattern 可以是一个特定的字符串,当然更常用的是正则表达式;input可以是一个文件,也可以是管道等,options取值有下面几种:
Option | Detail |
-n | 显示匹配的行号 |
-c | 统计匹配的行数 |
-i | 忽略字符大小写 |
-q | 静默模式,不输出任何信息,当我们只关心匹配结果时可以使用,然后使用echo $? 我们可以读出匹配的结果 |
-o | 仅显示匹配到的字符串 |
-v | 显示不被pattern匹配到的行 |
-Ax | 将匹配到的行以及后面的x行都显示出来 |
-Bx | 将匹配到的行以及前面的x行都显示出来 |
-Cx | 将匹配到的行以及前后的x行都显示出来 |
-e | 实现多个“pattern”的逻辑or关系 |
-w | 匹配整个单词 |
-E | 使用ERE,相当于egrep |
-F | 相当于fgrep,不支持正则表达式 |
来看几个列子,我们使用 grep 搜寻下meminfo 文件里面的”Slab”字符串:
1. –i选项可以让搜索忽略大小写,-n可以显示行数,-A3 可以打印出匹配到”slab”那行及其后三行:
2. –e选项可以实现“或”的功能,下面的搜索包含”slab”或者”bounce”的行,-E让搜索可以使用扩展正则表达式,“^(slab)”表示以slab开始的行:
3.-F选项表达这次搜索不支持正则表达式:
2. sed
Sed命令擅长的是取行进行分析。操作的基本流程是一行一行的读入数据放到一个被称为“pattern space”的缓存区间中去处理,处理完后打印到屏幕上。这里的“模式空间”也有一个对应的被称为“hold space ”缓冲区。这两者的关系,可以参考下面链接中的博文非常形象,容易理解:
https://blog.51cto.com/13691477/2113141
我们先来可以sed 命令的基本格式:
sed [options] program input
这里的action 操作可以放到一个脚本文件中,而-f 的选项可以让sed从脚本文件中取读取对应的action:
sed -f [options] script input
2.1 Options
Sed 支持的options 有:
options | Detail |
-i | 经过action处理后的数据会覆盖原来的数据,默认只显示不覆盖原来的数据 |
-r | action操作中的pattern 支持扩展正则表达式 |
-n | 只显示经过action处理的行,默认会显示文件的所有行以及action处理后的行 |
-e | 提供“或”选项 |
-h | 显示帮助信息 |
来看两个例子:
上例中的-i选项,让经过“action”处理过的行替换了原来的数据,-e 选项实现了“或”的功能。
上例中的-n 选项让只有经过“action”处理过的行才显示出来,没有-n选项时,原文件所有行以及处理过的那行都会显示。
2.2Program
Sed命令的program有“pattern”和“action”两部分,“pattern”用来找到符合规则的行,方式通常有以下三种:
- 空模式:空模式自然就是不指定任何模式,默认就是对所有行进行操作;
- 指定行号:指定具体的哪些行号;
- 正则表达式匹配:使用/RE/这种方式,也支持用/RE1/,/RE2/这种方式去指定行范围。
“Action”部分则用来对其进行处理,常用的命令则可以总结为:
Action | Detail |
p | 打印出匹配到的行 |
d | 删除行 |
a | 在匹配行后面增加,多行之间有“\n”隔开 |
i | 在匹配行前面增加,多行之间有“\n”隔开 |
c | 直接替换匹配行,多行之间有“\n”隔开 |
S | 替换字符串 |
g | 全局替换,对当前行中所有匹配的字符串进行替换,默认是只替换第一个 |
n | 删除模式空间中内容,读取下一行,并用下一个命令进行处理 |
! | 对所选行以外的行执行命令 |
q | 执行完匹配行之后推出sed命令 |
r | 从文件中读取行,放到匹配行的下面 |
w | 将匹配行写入文件,如果文件不存在则创建,存在则覆盖 |
h/H | 复制/追加pattern space的内容到hold space |
g/G | 复制/追加hold space的内容到pattern space |
X | 交换hold space和pattern space的内容 |
先来看看打印和删除的例子:
可以用指定行号或者正则表达式的方式来匹配行,正则表达式的格式请注意一定要用:“/RE/”的方式:
也可以用“,”的方式来指定 匹配的范围:
第二组我们来看下增加和替换的例子:
关于s/g 命令的使用:
-n 命令也非常有用,我们也来看个例子:用“/first/”匹配到了第一行,这时候我们将模式空间中这行删掉,并读取下一行,再用n命令的下一个命令p去处理模式空间中的内容:
再来看看r/w这两条命令的使用,命令r可以将rw.log 读出来插入到包含有”first”字符串的行后面;命令w可以将包含有“first”字符串的行插入文件rw.log中:
关于最后几条处理模式空间和保存空间的命令在之前介绍的链接中有比较形象的说明。
3. awk
awk专业术语叫报告分析器,简而言之,就是将文本数据处理成固定格式的类型,处理后的数据看起来就像是“报表”。
awk命令擅长的是取列分析,实际的操作流程也是逐行读入,然后对每行分成几列再按照具体的命令操作,其基本格式是:
awk [options] ‘pattern{action}’ input
在介绍这些参数之前我们先来看个例子看看awk 是怎么取行分析的:
从上图可以看出来,awk是以空格作为分隔符将数据分列,其中的第n列可以用$n读取到,$0则表示整行。了解了分列的方式后,我们逐个参数介绍下。
3.1 Option
Awk只有三个选项最常用:当使用脚本的方式执行命令时用”-f”选项;而”-F”选项则可以用来替换默认(空白字符)的分隔符;“-v选项”用来在program 外定义变量。
“-F”用来指定新的分割符,默认的分割符是空白字符。下例中默认的第一列的元素都是“This”;用”;”替换空白字符分割后,第一行没有“;”,整行可以看成1列,第二行中“;”前的都将被视为第一列。
-v 用以在program外定义变量。需要注意的一点是,awk 同样是以行为单位来进行处理,所以下面的打印test 变量的操作每行都会执行一次:
3.2 变量
Awk命令支持的变量有自定义变量和内置变量两种。
关于自定义变量:可以使用-v 选项定义,也可以在’program’中直接定义;另外除了表示列的 ‘$n’除外,引用时不需要加“$”前缀。
awk也定义了多个内置变量,常用的内置变量可以总结为:
Variable | Detail |
NR | 行号,当前处理的文本行行号 |
NF | 列数,当前行字段的个数 |
FNR | 各个文件分别计数的行号 |
FS | 输入分隔符,默认是空白字符 |
OFS | 输出分隔符,默认是空白字符 |
RS | 输入的换行符,默认是”\n” |
ORS | 输出的换行符,默认是”\n” |
FILENAME | 当前文件名 |
ARGC | 命令行参数个数 |
ARGV | 命令行各参数 |
1. NR,NF,FNR这三个变量很好理解,分别表示行数,列数,以及将多个文件的行数分别计数:
2. FS和OFS变量用来指定输入和输出分隔符,FS 等同于“-f”的功能,而OFS则是用来修改输出格式,将默认的字段中间的空白字符换成指定字符:
3. 默认的换行符是”\n”,可是如果我们想自己指定换行符,RS和ORS可以实现。下面的例子中使用空格作为默认的输入换行符,这样原本的一行“This is first line”变成了四行:
理解了上面的例子,我们再来看看ORS的实例:
4. 最后一组来看看参数类的变量ARGC, ARGV。学过C语言的应该对这两个单词很熟悉,argc表示参数个数,argv是参数数组。同样我们先来看个例子:
上面的命令读出来的参数有3个,那分别是哪三个呢?
和C语言一样,ARGV[0]表示程序的名字,另外两个参数是两个文件名。
这里需要注意的是用了BEGIN模式,如果不用会怎么样?
每个文件的每一行都会输出一遍结果,正如前面所述,awk也是根据行来处理的。
3.3 Pattern
Awk命令的pattern参数同样是为了匹配到特定的行,其类型主要有以下几种:
- 空模式:默认是对所有行进行操作
- 正则表达式:awk 的正则表达式默认是扩展正则表达式;
- 运算符:可以根据关系运算符来匹配到特定的行,或者执行特定操作;
- BEGIN/ENG(不是用来匹配,而是在处理文件前后做一些特殊的操作)。
1. 运算符
Awk支持多种多种运算符操作,我们在这里先做个简单的总结:
运算符类型 | 运算符 | 描述 |
算术运算符 | + - * / % ^ | 算术操 |
关系运算符 | > >= < <= == != | 比较操作 |
~ ~! | 与正则表达式匹配 | |
逻辑运算符 | && || ! | 与/或/非操作 |
赋值运算符 | = | 可与算术运算符结合,如 += |
条件运算符 | ?: | Expression ? var : var |
其它运算符 | in | 数组中是否存在某个元素 |
其中关系运算符支持用多种算术运算符来设定匹配的条件:
大家比较陌生的可能是“~” “ ~!”这两个关系运算符,“~”是指与正则表达式匹配,加一个感叹号”!~”自然表示与正则表达式不匹配,这两个运算符常用于变量比较。
2. BEGIN/END
前面多次提到,awk也是针对行进行操作。如果是对所有行进行操作的话,那对应的执行操作每行都会做一次。而BEGIN和END 模式可以让我们在对文件处理前后先执行一些特别的action。这两个pattern 示例如下:
需要注意的是BEGIN和END这两种pattern 中对应的action操作是读不到内置变量的。
3.4 Action
Action部分表示awk 需要去对匹配的行执行哪些操作,前面一直在用的print 命令就是一种actin。此外,awk还支持多种action,比如if…else…语句,while语句,for语句等等。
这些语句的使用和C语言中的用法基本一样。 关于printf命令与print命令的主要差异是printf支持自定义输出格式,而print默认输出换行符:
3.5 数组
Awk命令也支持数组的方式,数组也是各种编程语言的基本类型,关于awk的数组类型,主要注意以下方面:
- 不需要先定义再使用,默认的值为空白字符:
- 使用关键字“in”去判断是否存在某个元素,而不是值是否是空白字符的方式;因为使用数组的定义就会默认定义它:
- 使用关键字deleta去删除:
- 支持关联数组,关联数组的意思是,不是用数字表示下标,而可以自定义字符串表示:
需要注意的是这里自动以的index 如果是字符串,也要用“”或者‘’去表示。
最后我们来看个示例,看看数组和for 语句是怎么结合起来的: