grep 、sed、awk被称为linux中的"三剑客"。
总结一下这三个"剑客"的特长。
grep 更适合单纯的查找或匹配文本
sed 更适合编辑匹配到的文本
awk 更适合格式化文本,对文本进行较复杂格式处理
参考:awk从放弃到入门(1):awk基础 (通俗易懂,快进来看)

@[TOC]

(一)sed命令 基本用法

已知quote.txt文件内容如下:

The honeysuckle band played all night long for only $90.
It was an evening of splendid music and company.
Too bad the disco floor fell through at 23:10.
The local nurse Miss P.Neave was in attendance. 

试编写sed命令实现如下功能。(按模式串替换/按行替换、追加、删除、查找)

(1)删除$符号。

cat -n quote.txt | sed 's/$//g'

运行结果:
在这里插入图片描述
(2)显示包含music文字的行内容及行号。

cat -n quote.txt | sed -n '/music/p'

运行结果:
在这里插入图片描述
(3)在第4行后面追加文件“hello world!”。

cat -n quote.txt | sed '4a hello world'

运行结果:
在这里插入图片描述
(4)将文本中的所有“The”都修改为“Ok”。

cat -n quote.txt | sed 's/The/Ok/g'

运行结果:
在这里插入图片描述
(5)将第3行内容替换为“This is the third line.”。

cat -n quote.txt | sed '3c This is the third line.'

运行结果:
在这里插入图片描述
(6)删除第2行内容。

cat -n quote.txt | sed '2d'

运行结果:
在这里插入图片描述
(7)设置shell变量var的值为evening,用sed命令查找匹配var变量值的行。

var=evening
echo $var
cat -n quote.txt | sed -n "/$var/p"

运行结果:
在这里插入图片描述
注意,"/$var/p"必须是双引号!如果是单引号则\$var将被认为是字符串“$var”
只要没有用变量,双引号改成单引号没有关系,结果是一样的,但是用了变量就必须是双引号!

(8)-i,修改原文件,并且显示出单引号和双引号的区别。

sed -i '4a $var' quote.txt  # 在文件第4行末尾添加字符串"$var",并且修改原文件
cat -n quote.txt
sed -i "4a $var" quote.txt  # 在文件第4行末尾添加变量var的内容,并且修改原文件
cat -n quote.txt

运行结果:
在这里插入图片描述

(二)awk命令 基本用法

awk [options] 'program' file1, file2, ...
对于上述语法中的program来说,又可以细分成pattern和action,也就是说,awk的基本语法如下:
awk [options] 'Pattern{Action}' file

事先准备awk_test.txt和data.txt。

awk_test.txt文件内容如下(每个冒号前后都有空格):

one : two : three
four : five : six

data.txt文件内容如下:

1 2 3
4 5
6 7 8 9

(1)空格做分隔符,显示文件第2列的内容。

awk 'BEGIN{FS=" "}{print $2}' awk_test.txt

运行结果:
在这里插入图片描述
(2)冒号做分隔符,显示文件第2列的内容。

awk 'BEGIN{FS=":"}{print $2}' awk_test.txt

加上BEGIN是为了使得第一行也按冒号做分隔符,否则第一行会默认按空格做分隔符。

运行结果:
在这里插入图片描述
(3)循环打印出文件中所有的字段。

①遍历所有字段

awk '{for(i=1;i<=NF;i++)print $i}' data.txt

NF表示字段数。
看awk单引号中的代码,是不是很像C语言?for就像C语言的循环,括号括起来就像代码块(在awk中的术语中被称作“Action”)。

运行结果:
在这里插入图片描述
②遍历前两行所有字段

awk '{for(i=1;i<=NF;i++)if(NR<=2)print $i}' data.txt

NR表示行数。 if语法、for语法和C语言相同,print语法不同。

运行结果:
在这里插入图片描述
③遍历前两行所有字段,并同时加上一个数x

awk '{x=10}{for(i=1;i<=NF;i++)if(NR<=2)print $i+x}' data.txt

运行结果:
在这里插入图片描述
(4)已知文件data.txt中都是数字,数字之间以空格作为分隔符,试将data.txt里的所有偶数输出,并输出偶数的个数。要求判断每个数字是否为偶数,即要求程序里包含循环和分支结构。

awk '{for(i=1;i<=NF;i++)if($i%2==0){print $i;sum++}}END{print "sum="sum}' data.txt

注意:END表示处理完所有行之后需要执行的操作;print sum的时候sum不能加$。

运行结果:
在这里插入图片描述

AWK 包含两种特殊的模式:BEGIN 和 END。
BEGIN 模式指定了处理文本之前需要执行的操作。
END 模式指定了处理完所有行之后需要执行的操作。

(三)利用awk命令 编写shell脚本

已知脚本awk.sh的内容如下,试通过运行该脚本,理解该脚本实现的功能。(事先准备好quote.txt)

#!/bin/bash
read -p "enter search pattern: " pattern
awk "/$pattern/"'{ nmatches++; print } END { print nmatches " found." }' quote.txt

功能:输入要匹配的模式串,程序返回模式串所在行的内容以及出现的次数。

模式串为"The":
在这里插入图片描述
模式串为"a":
在这里插入图片描述