awk、grep、sed是linux操作文本的三大利器,合称文本三剑客,也是运维人必须掌握的linux命令。三者的功能都是处理文本,但侧重点各不相同,其中属awk功能最强大,但也最复杂。grep更适合单纯的查找或匹配文本,sed更适合编辑匹配到的文本,awk更适合格式化文本,对文本进行较复杂格式处理。

1 grep

1.1 什么是 grep 和 egrep

Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来(匹配到的标红)。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。
grep的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容。

grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。
egrep = grep -E:扩展的正则表达式 (除了\< , > , \b 使用其他正则都可以去掉\)

1.2 使用 grep

1.2.1 命令格式

  1. grep [option] pattern file

1.2.2 命令功能

用于 过滤/搜索 特定字符。可使用正则表达式能多种命令配合使用,使用上十分灵活。

1.2.3 命令参数

  1. -A<显示行数> 除了显示符合范本样式的那一列之外,并显示该行之后的内容。
  2. -B<显示行数> 除了显示符合样式的那一行之外,并显示该行之前的内容。
  3. -C<显示行数> 除了显示符合样式的那一行之外,并显示该行之前后的内容。
  4. -c 统计匹配的行数
  5. -e 实现多个选项间的逻辑or 关系 (grep -e 只能传递一个检索内容)
  6. -E 扩展的正则表达式 (可以传递多个内容 ,使用 | 来分隔多个pattern,以此实现OR操作)
  7. -f FILE FILE获取PATTERN匹配
  8. -F 相当于fgrep
  9. -i --ignore-case 忽略字符大小写的差别。
  10. -n 显示匹配的行号
  11. -o 仅显示匹配到的字符串
  12. -q 静默模式,不输出任何信息
  13. -s 不显示错误信息。
  14. -v 显示不被pattern 匹配到的行,相当于[^] 反向匹配
  15. -w 匹配整个单词

1.3 grep实战演示

image1112.jpg

2 正则表达式

2.1 认识正则

正则表达式应用广泛,在绝大多数的编程语言都可以完美应用,在Linux中,也有着极大的用处。
使用正则表达式,可以有效的筛选出需要的文本,然后结合相应的支持的工具或语言,完成任务需求。
正则表达式可以使用正则表达式引擎实现,正则表达式引擎是解释正则表达式模式并使用这些模式匹配文本的基础软件。

2.2 基本正则表达式

2.2.1 匹配字符

  1. . 匹配任意单个字符,不能匹配空行
  2. [] 匹配指定范围内的任意单个字符
  3. [^] 取反
  4. [:alnum:] [0-9a-zA-Z]
  5. [:alpha:] [a-zA-Z]
  6. [:upper:] [A-Z]
  7. [:lower:] [a-z]
  8. [:blank:] 空白字符(空格和制表符)
  9. [:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
  10. [:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
  11. [:digit:] 十进制数字 或[0-9]
  12. [:xdigit:]十六进制数字
  13. [:graph:] 可打印的非空白字符
  14. [:print:] 可打印字符
  15. [:punct:] 标点符号

image2.jpg

2.2.2 配置次数

  1. * 匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配
  2. .* 任意长度的任意字符,不包括0
  3. \? 匹配其前面的字符0 1
  4. \+ 匹配其前面的字符至少1
  5. \{n\} 匹配前面的字符n
  6. \{m,n\} 匹配前面的字符至少m 次,至多n
  7. \{,n\} 匹配前面的字符至多n
  8. \{n,\} 匹配前面的字符至少n

image.png

2.2.3 位置锚定:定位出现的位置

^                                  行首锚定,用于模式的最左侧
$                                  行尾锚定,用于模式的最右侧
^PATTERN$,              用于模式匹配整行
^$                                 空行
^[[:space:]].*$   空白行
\< 或 \b                   词首锚定,用于单词模式的左侧
\> 或 \b                   词尾锚定;用于单词模式的右侧
\<PATTERN\>

image.png

2.2.4 分组和后向引用

# 分组:\(\) 将一个或多个字符捆绑在一起,当作一个整体进行处理
分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...

# 后向引用
引用前面的分组括号中的模式所匹配字符,而非模式本身
\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符
\2 表示从左侧起第2个左括号以及与之匹配右括号之间的模式所匹配到的字符,以此类推
\& 表示前面的分组中所有字符

流程分析如下:
Linux文本三剑客 ---- grep sed awk - 图5
image.png

2.3 扩展正则表达式

# 字符匹配:
 .                                          任意单个字符
 []                                          指定范围的字符
 [^]                                         不在指定范围的字符

 # 次数匹配:
 *                                             匹配前面字符任意次
 ?                                          0 或1次
 +                                             1 次或多次
 {m}                                         匹配m次 次
 {m,n} :                             至少m ,至多n次

# 位置锚定:
 ^                                            行首
 $                                             行尾
 \<, \b                                    语首
 \>, \b                                    语尾

# 分组:()
#后向引用:\1, \2, ...

egrep = grep -E:扩展的正则表达式 (除了\< , > , \b 使用其他正则都可以去掉\)
image.png

3 sed

3.1 认识 sed

sed 是一种流编辑器它一次处理一行内容。处理时,把当前处理的 行 存储在临时缓冲区中,称为“模式空间”(pattern space ),接着用sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如 ‘D’ 的特殊命令,那会在两个循环之间清空模式空间,但不会清空 保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用**重定向存储输出 或 -i **。
功能:主要用来自动编辑一个或多个文件, 简化对文件的反复操作

3.2 使用 sed

3.2.1 命令格式

sed [options] '[地址定界] command' file(s)

3.2.2 常用选项 options

-n:                不输出模式空间内容到屏幕,即不自动打印,只打印匹配到的行
-e:                多点编辑,对每行处理时,可以有多个Script
-f:                把Script写到文件当中,在执行sed时-f 指定文件路径,如果是多个Script,换行写
-r:                支持扩展的正则表达式
-i:                直接将处理的结果写入文件
-i.bak:        在将处理的结果写入文件之前备份一份

3.2.3 地址定界

不给地址:对全文进行处理

单地址:(这里 # 代表行号数字)
#: 指定的行          例:sed -n "1p" demo.txt (打印第1行)
/pattern/:        被此处模式所能够匹配到的每一行 

地址范围:
#,#            例:sed -n "1,2p" demo.txt (打印第1行和第2行)
#,+#                     例:sed -n "5,+4" demo.txt (打印第5行和紧跟该行之后的4行)     
/pat1/,/pat2/  例:sed -n "/aa/,/AB/p" demo.txt (打印包含有 aa 和 AB 的行【一次匹配】,以及两行中间所有行)
#,/pat1/       例:sed -n "3,/CD/p" demo.txt (打印第三行和包含 CD 的行【一次匹配】,以及两行中间的所有行)
~:步进
sed -n '1~2p'  只打印奇数行 (1~2 从第1行,一次加2行)
sed -n '2~2p'  只打印偶数行 (2~2 从第1行,一次加2行)

3.2.4 编辑命令 command

d:         删除模式空间匹配的行,并立即启用下一轮循环
p:         打印当前模式空间内容,追加到默认输出之后
a:         在指定行后面追加文本,支持使用\n实现多行追加
i:         在行前面插入文本,支持使用\n实现多行追加
c:         替换行为单行或多行文本,支持使用\n实现多行追加
w:         保存模式匹配的行至指定文件
r:         读取指定文件的文本至模式空间中匹配到的行后
=:         为模式空间中的行打印行号
!:         模式空间中匹配行取反处理
s///:     查找替换,支持使用其它分隔符,如:s@@@ , s### ;
        加g表示行内全局替换;
        在替换时,可以加一下命令,实现大小写转换
        \l:把下个字符转换成小写。
        \L:把replacement字母转换成小写,直到\U或\E出现。
        \u:把下个字符转换成大写。
        \U:把replacement字母转换成大写,直到\L或\E出现。
        \E:停止以\L或\U开始的大小写转换

3.3 sed 用法演示

3.3.1 常用选项 options 演示

#匹配到的行会打印一遍,不匹配的行也会打印
image.png
#-n 不显示没匹配的行
image.png
#-e 多点编辑
image.png
#-f 使用文件处理
image.png
#-i 直接对文件进行处理(i.bak 加备份)
image.png

3.3.2 地址界定演示

#不指定行,打印全文
image.png
#替换第2行所有的b->B
image.png
#打印1-2行
image.png
#将奇数行的a或A替换为E
image.png
打印包含有 aa 和 AB 的行【一次匹配】,以及两行中间所有行
image.png

3.3.3 编辑命令 command 演示

#删除第2行
image.png
#打印第2行
image.png
#在第2行后加12345
image.png
#在第1行前加1234567
image.png
#替换第3行内容为1234567
image.png
#保存第3行的内容到demo3.txt文件中
image.png
#读取demo3.txt的内容到第1行后
image.png
#打印行号

image.png
#将全文的小写字母替换为大写字母 (& 符号代表保存查找串以便在替换串中引用)
image.png

3.4 sed 高级编辑命令

3.4.1 格式

h:        把模式空间中的内容覆盖至保持空间中
H:        把模式空间中的内容追加至保持空间中
g:        从保持空间取出数据覆盖至模式空间
G:        从保持空间取出内容追加至模式空间
x:        把模式空间中的内容与保持空间中的内容进行互换
n:        读取匹配到的行的下一行覆盖 至模式空间
N:        读取匹配到的行的下一行追加 至模式空间
d:        删除模式空间中的行
D:        删除 当前模式空间开端至\n 的内容(不再传 至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed

3.4.2 一个案例+示意图演示

#案例:倒序输出文本内容
image.png
#示意图如下:
Linux文本三剑客 ---- grep sed awk - 图28
#总结模式空间与保持空间关系:
保持空间是模式空间一个临时存放数据的缓冲区,协助模式空间进行数据处理

3.4.3 演示

#显示偶数行
image.png
#显示奇数行
image.png
#倒序显示
image.png
#显示最后一行
image.png
#每行之间加空行
image.png
#把每行内容替换成空行
image.png
#确保每一行下面都有一个空行
image.png

4 awk

4.1 认识 awk

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。
awk其实不仅仅是工具软件,还是一种编程语言。不过,本文只介绍它的命令行用法,对于大多数场合,应该足够用了。

4.2 使用 awk

4.2.1 语法

awk [options] 'program' var=value file…
awk [options] -f programfile var=value file…
awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...

4.2.2 常用命令选项

-F fs                        fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value        赋值一个用户定义变量,将外部变量传递给awk
-f scripfile        从脚本文件中读取awk命令

4.3 awk 变量

变量:内置和自定义变量,每个变量前加 -v 命令选项

4.3.1 内置变量

格式

FS                         输入字段分隔符,默认为空白字符
OFS                        输出字段分隔符,默认为空白字符
RS                         输入记录分隔符,指定输入时的换行符,原换行符仍有效
ORS                     输出记录分隔符,输出时用指定符号代替换行符
NF                         字段数量,共有多少字段, $NF引用最后一列,$(NF-1)引用倒数第2列
NR                         行号,后可跟多个文件,第二个文件行号继续从第一个文件最后行号开始
FNR                     各文件分别计数, 行号,后跟一个文件和NR一样,跟多个文件,第二个文件行号从1开始
FILENAME             当前文件名
ARGC                     命令行参数的个数
ARGV                     数组,保存的是命令行所给定的各参数,查看参数

演示

image (1)1.jpgimage (2)1.jpg

4.3.2 自定义变量

自定义变量( 区分字符大小写)

-v var=value

先定义变量,后执行动作print
image.png
先执行动作print,后定义变量
image.png
在program 中直接定义
可以把执行的动作放在脚本中,直接调用脚本 -f
image.png

4.4 printf 命令

比print更强大

4.4.1 格式

格式化输出

printf "FORMAT", item1,item2, ...
  • 必须指定FORMAT
  • 不会自动换行,需要显式给出换行控制符 **\n**
  • FORMAT 中需要分别为后面每个item 指定格式符

格式符:与item一一对应

%c                 显示字符的ASCII码
%d, %i         显示十进制整数
%e, %E        显示科学计数法数值
%f                 显示为浮点数,小数【%5.1f,带整数、小数点、整数共5位,小数1位,不够用空格补上】
%g, %G         以科学计数法或浮点形式显示数值
%s              显示字符串;例:%5s最少5个字符,不够用空格补上,超过5个还继续显示
%u                 无符号整数
%%                显示% 自身

修饰符:放在%c[/d/e/f…]之间

#[.#]            第一个数字控制显示的宽度;第二个# 表示小数点后精度,%5.1f
-                    左对齐(默认右对齐) %-15s
+                    显示数值的正负符号 %+d

4.4.2 演示

image.png

awk -F: '{printf "%20s---%u\n",$1,$3}' /etc/passwd

WX20210118-113444@2x.jpg

> awk -F: '{printf "%-20s---%-10.3f\n",$1,$3}' /etc/passwd

WX20210118-113513@2x.jpg

awk -F: 'BEGIN{printf "username            userid\n-----------------------------\n"}{printf "%-20s|%-10.3f\n",$1,$3}' /etc/passwd

image.png

4.5 操作符

4.5.1 格式

  • 算术操作符:

    •  x+y, x-y, x*y, x/y, x^y, x%y
    •  -x:  转换为负数
    •  +x:  转换为数值
    
  • 字符串操作符:没有符号的操作符,字符串连接

  • 赋值操作符:

    =, +=, -=, *=, /=, %=, ^=
    ++, --
    
  • 比较操作符:

    ==, !=, >, >=, <, <=
    
  • 模式匹配符:**~ :左边是否和右边匹配包含 !~** :是否不匹配

  • 逻辑操作符:与**&& ,或|| ,非!**
  • 函数调用: function_name(argu1, argu2, …)
  • 条件表达式(三目表达式):selector?if-true-expression:if-false-expression

    注释:先判断,如果符合执行 ? 后的操作;否则执行 : 后的操作

    4.5.2 演示

    模式匹配符
    WX20210118-125304@2x.jpg
    逻辑操作符
    image.png
    条件表达式(三目表达式)

    awk -F: '{$3 >= 1000?usertype="common user":usertype="sysadmin user";print usertype,$1,$3}' /etc/passwd
    

    image.png

    4.6 awk PATTERN 匹配部分

    4.6.1 格式

    PATTERN:根据pattern 条件,过滤匹配的行,再做处理

    如果未指定:空模式,匹配每一行
    /regular expression/ :仅处理能够模式匹配到的行,正则,需要用/ / 括起来
    relational expression:关系表达式,结果为“真”才会被处理
                                              真:结果为非0值,非空字符串
                                              假:结果为空字符串或0值        
    line ranges:行范围
                          startline(起始行),endline(结束行):/pat1/,/pat2/  不支持直接给出数字,可以有多段,中间可以有间隔
    BEGIN/END 模式
                      BEGIN{}:  仅在开始处理文件中的文本之前执行一次
                      END{} :仅在文本处理完成之后执行
    

    4.6.2 演示

    WX20210118-1325131111.jpg

    4.7 awk有意思的案例

    WX20210118-133338@2x.jpg

    5 awk 高阶用法

    5.1 awk 控制语句—if-else判断

    语法

    if(condition){statement;…}[else statement]  双分支
    if(condition1){statement1}else if(condition2){statement2}else{statement3}  多分支
    

    使用场景
    对awk 取得的整行或某个字段做条件判断

    演示**

    awk -F: '{if($3>10 && $3<1000)print $1,$3}' /etc/passwd
    

    image.png

    awk -F: '{if($NF=="/bin/zsh") print $1,$NF}' /etc/passwd
    

    image.png
    WX20210118-133338@2x111.jpg

    5.2 awk 控制语句—while循环

    语法

    while(condition){statement;…}
    

    注:条件真”,进入循环;条件“假”, 退出循环
    使用场景

  • 对一行内的多个字段逐一类似处理时使用

  • 对数组中的各元素逐一处理时使用


演示
WX20210118-135956@2x.jpg**

5.3 awk控制语句 —— do-while 循环

语法

do {statement;…}while(condition)

意义
无论真假,至少执行一次循环体
计算1+2+3+…+100=5050
image.png

5.4 awk控制语句 —— for 循环

语法

for(expr1;expr2;expr3) {statement;…}

特殊用法
遍历数组中的元素

for(var in array) {for-body}

演示

WX20210118-140833@2x.jpg
难!!!!WX20210118-141117@2x.jpg
难!!!!

5.5 和 shell 脚本中较相似的控制语句

5.5.1 switch 语句

和shell中的case很像

switch(expression) {case VALUE1 or /REGEXP/:statement1; case VALUE2 or /REGEXP2/: statement2;...; default: statementn}

5.5.2 break 和 continue

WX20210118-142001@2x.jpg

5.5.3 next

next:提前结束对本行处理而直接进入下一行处理(awk 自身循环)
WX20210118-142257@2x.jpg

5.6 awk 数组

5.6.1 关联数组:array [index-expression]

可使用任意字符串;字符串要使用双引号括起来
如果某数组元素事先不存在,在引用时,awk 会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
若要遍历数组中的每个元素,要使用for 循环:for(var in array) {for-body}

5.6.2 演示

awk 使用数组
WX20210118-142738@2x.jpg
分析:把每行作为下标,第一次进来,相当于print i as…一样结果为空,打印空,!取反结果为1,打印本行,并且++变为不空,下次进来相同的行就是相同的下标,本来是上次的值,!取反为空,不打印,++变为不空,所以每次重复进来的行都不打印

数组遍历**
image.png

5.6.3 数值\字符串处理

数值处理

rand():返回0和1之间一个随机数,需有个种子 srand(),没有种子,一直输出0.237788

WX20210118-143902@2x.jpg
字符串处理
image.png

5.7 awk 自定义函数

格式
和bash区别:定义函数()中需加参数,return返回值不是$?,是相当于echo输出

function name ( parameter, parameter, ... ) {
    statements
    return expression
}

演示
image.png

5.8 awk 中调用 shell 命令

5.8.1 system 命令

空格是awk 中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk 的变量外其他一律用”” 引用 起来。
image.png

5.8.2 awk 脚本

将awk 程序写成脚本,直接调用或执行
image.png

5.8.3 向 awk 脚本传递参数

格式

awkfile var=value var2=value2... Inputfile

注意 :在BEGIN 过程 中不可用。直到 首行输入完成以后,变量才可用 。可以通过-v 参数,让awk 在执行BEGIN 之前得到变量的值。命令行中每一个指定的变量都需要一个-v
示例
image.png

6 grep awk sed对比

  • grep 主要用于搜索某些字符串;
  • sed,awk 用于处理文本


grep基本是以行为单位处理文本的;
而awk可以做更细分的处理,通过指定分隔符将一行(一条记录)划分为多个字段,以字段为单位处理文本。**

awk中支持C语法,可以有分支条件判断、循环语句等,相当于一个小型编程语言。
awk功能比较多是一个编程语言了。 grep功能简单,就是一个简单的正则表达式的匹配。 awk的功能依赖于grep。
grep可以理解为主要作用是在一个文件中查找过滤需要的内容。awk不是过滤查找,而是文本处理工具,是把一个文件处理成你想要的格式。
AWK的功能是什么?与sed和grep很相似,awk是一种样式扫描与处理工具。但其功能却大大强于sed和grep。
awk提供了极其强大的功能:它几乎可以完成grep和sed所能完成的全部工作,同时,它还可以可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上,awk的确拥有自己的语言:awk程序设计语言,awk的三位创建者已将它正式定义为:样式扫描和处理语言。
使用awk的第一个理由是基于文本的样式扫描和处理是我们经常做的工作,awk所做的工作有些象数据库,但与数据库不同的是,它处理的是文本文件,这些文件没有专门的存储格式,普通的人们就能编辑、阅读、理解和处理它们。而数据库文件往往具有特殊的存储格式,这使得它们必须用数据库处理程序来处理它们。既然这种类似于数据库的处理工作我们经常会遇到,我们就应当找到处理它们的简便易行的方法,UNIX有很多这方面的工具,例如sed 、grep、sort以及find等等,awk是其中十分优秀的一种。
使用awk的第二个理由是awk是一个简单的工具,当然这是相对于其强大的功能来说的。的确,UNIX有许多优秀的工具,例如UNIX天然的开发工具C语言及其延续C++就非常的优秀。但相对于它们来说,awk完成同样的功能要方便和简捷得多。这首先是因为awk提供了适应多种需要的解决方案:从解决简单问题的awk命令行到复杂而精巧的awk程序设计语言,这样做的好处是,你可以不必用复杂的方法去解决本来很简单的问题。例如,你可以用一个命令行解决简单的问题,而C不行,即使一个再简单的程序,C语言也必须经过编写、编译的全过程。其次,awk本身是解释执行的,这就使得awk程序不必经过编译的过程,同时,这也使得它与shell script程序能够很好的契合。最后,awk本身较C语言简单,虽然awk吸收了C语言很多优秀的成分,熟悉C语言会对学习awk有很大的帮助,但awk本身不须要会使用C语言——一种功能强大但需要大量时间学习才能掌握其技巧的开发工具。
使用awk的第三个理由是awk是一个容易获得的工具。与C和C++语言不同,awk只有一个文件(/bin/awk),而且几乎每个版本的UNIX都提供各自版本的awk,你完全不必费心去想如何获得awk。但C语言却不是这样,虽然C语言是UNIX天然的开发工具,但这个开发工具却是单独发行的,换言之,你必须为你的UNIX版本的C语言开发工具单独付费(当然使用D版者除外),获得并安装它,然后你才可以使用它。
于以上理由,再加上awk强大的功能,我们有理由说,如果你要处理与文本样式扫描相关的工作,awk应该是你的第一选择。在这里有一个可遵循的一般原则:如果你用普通的shell工具或shell script有困难的话,试试awk,如果awk仍不能解决问题,则便用C语言,如果C语言仍然失败,则移至C++。

sed是一个非交互性文本流编辑器。它编辑文件或标准输入导出的文本拷贝。sed编辑器按照一次处理一行的方式来处理文件(或者输入)并把输出送到屏幕上。你可以在vi和ex/ed编辑器里识别他的命令。sed把当前正在处理的行保存在一个临时缓存里,这个缓存叫做模式空间。一但sed完成了对模式空间里的行的处理(即对该行执行sed命令),就把模式空间的行送到屏幕上(除非该命令要删除该行活禁止打印)。处理完该行之后,从模式空间里删除它,然后把下一行读入模式空间,进行处理,并显示。当输入文件的最后一行处理完后,sed终止。通过把每一行存在一个临时缓存里并编辑该行,初始文件不会被修改或被破坏。