从 0 到 1 学 sed 与 awk:Linux 文本处理的两把 “瑞士军刀”
一、SED是什么
1.1
sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。sed也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于Shell脚本中,用以完成各种自动化处理任务。
二、sed 的原理
sed 的工作流程主要包括读取、执行和显示三个过程。
读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
常见的 sed 命令选项主要包含以下几种。
-e 或--expression=:表示用指定命令或者脚本来处理输入的文本文件。
-f 或--file=:表示用指定的脚本文件来处理输入的文本文件。
-h 或--help:显示帮助。
-n、--quiet 或 silent:表示仅显示处理后的结果。
-i.bak:直接编辑文本文件。
-r, -E 使用扩展正则表达式
-s 将多个文件视为独立文件,而不是单个连续的长文件流
三、sed命令用法
3.1输出符合条件的文本(p 表示正常输出)
输出所有内容,等同于 cat demo
sed -n '3p' demo //输出第 3 行
sed -n '3,5p' demo //输出 3~5 行
sed -n 'p;n' demo 输出所有奇数行,n 表示读入下一行资料
sed -n 'n;p' demo 输出所有偶数行,n 表示读入下一行资料
sed -n '1,5{p;n}' demo 输出第 1~5 行之间的奇数行(第 1、3、5 行)
sed -n '10,${n;p}' demo 输出第 10 行至文件尾之间的偶数行
ifconfig ens33|sed -n 2p #直接显示第二行内容
sed 命令与正则表达式相结合
sed -n '/the/p' demo //输出包含the 的行
sed -n '4,/the/p' demo //输出从第 4 行至第一个包含 the 的行
sed -n '/the/=' demo
//输出包含the 的行所在的行号,等号(=)用来输出行号
sed -n '/^PI/p' demo //输出以PI 开头的行
sed -n '/[0-9]$/p' demo //输出以数字结尾的行
sed -n '/\<wood\>/p' demo //输出包含单词wood 的行
3.2 删除符合条件的文本(d)
nl demo | sed '3d' //删除第 3 行
nl demo | sed '3,5d' //删除第 3~5 行
nl demo |sed '/cross/d' //删除匹配所有包含 cross 的行。
sed '/\.$/d' demo //删除以"."结尾的行
sed '/^$/d' demo //删除所有空行
注 意 : 若 是 删 除 重 复 的 空行 , 即 连 续 的 空 行 只 保 留 一 个 , “cat -s demo”。
3.3 替换符合条件的文本
sed 's/the/THE/' demo //将每行中的第一个the 替换为 THE
sed 's/l/L/2' demo //将每行中的第 2 个 l 替换为 L
sed 's/o//g' demo //将文件中的所有o 删除(替换为空串)
sed 's/^/#/' demo //在每行行首插入#号
3.4 迁移符合条件的文本
在使用 sed 命令迁移符合条件的文本时,常用到以下参数.
H:复制到剪贴板;
g、G:将剪贴板中的数据覆盖/追加至指定行;
w:保存为文件;
r:读取指定文件;
a:追加指定内容。具体操作方法如下所示。
I,i 忽略大小写
示例:
sed '/the/{H;d};$G' demo //将包含the 的行迁移至文件末尾,{;}用于多个操作
sed '1,5{H;d};17G' demo //将第 1~5 行内容转移至第 17 行后
sed '/the/w out.file' demo //将包含the 的行另存为文件 out.file
sed '/the/r /etc/hostname' demo //将文件/etc/hostname 的内容添加到包含 the 的每行以后
sed '3aNew' demo //在第 3 行后插入一个新行,内容为New
sed '/the/aNew' demo //在包含the 的每行后插入一个新行,内容为 New
sed '3aNew1\nNew2' demo 在第 3 行后插入多行内容,中间的\n 表示换行
四、awk分析文本工具
4.1 awk 是什么
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作
数据可以来自标准输入也可以是管道或文件
20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
4.2 awk工作原理
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出,如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较、倾向于将一行分成多个""字段"然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。在使用awk命令的过程中,可以使用逻辑操作符" &&"表示"与"、"||表示"或"、"!"表示非";还可以进行简单的数学运算,如+、一、*、/、%、^分别表示加、减、乘、除、取余和乘方。
4.2.1工作流程
pattern [ˈpætn] 模式 ; process [ˈprəʊses] 处理
任何 awk 语句都是由模式和动作组成,一个 awk 脚本可以有多个语句。模式决定动作语句的触发条件
和触发时间。
在 linux 上常用的是 gawk,awk 是 gawk 的链接文件
awk---->gawk 即: gun awk
[root@benet22 opt]# which awk
/usr/bin/awk
[root@benet22 opt]# ll `which awk`
lrwxrwxrwx. 1 root root 4 8月 19 2022 /usr/bin/awk -> gawk
4.2.2 执行流程
BEGIN 语句设置计数和打印头部信息,在任何动作之前进行
END 语句输出统计结果,在完成动作之后执行
AWK执行的流程非常简单:读(Read)、执行(Execute)与重复
4.3基本语法
awk 选项' 模式或条件{操作}' 文件1 文件2 ...
awk -f 脚本文件 文件1 文件2 ..
格式:awk关键字 选项 命令部分 '{xxxx}' 文件名
**AWK 支持两种不同类型的变量:内建变量(可直接使用),自定义变量awk 内置变量(预定义变量)
FS:指定每行文本的字段分隔符,默认为空格或制表位。
NF:当前处理的行的字段个数。在执行过程中对应于当前的字段数,NF:列的个数
NR:当前处理的行的行号(序数)。 在执行过程中对应于当前的行号
$0:当前处理的行的整行内容。
$n:当前处理行的第 n 个字段(第 n 列)。比如: $1 表示第一个字段,$2 表示第二个字段
FILENAME:被处理的文件名(当前输入文件的名)。
FNR 各文件分别计数的行号
OFS 输出字段分隔符(默认值是一个空格)
ORS 输出记录分隔符(默认值是一个换行符)
RS:行分隔符。awk从文件上读取资料时,将根据Rs的定义把资料切割成许多条记录, 而awk一次仅读
入一条记录,以进行处理。预设值是" \n'
5、实战案列
5.1案例文本
awk '{print "hello"}' < /etc/passwd #/etc/passwd中文件的内容有多少行“hello”就打印多少次
awk '{print}' zz
awk '{print $1}' zz
awk -F: '{print $5}' zz //自定义冒号为分隔符显示分隔之后的第五列
awk -Fx '{print $1}' /etc/passwd
awk -F: '{print $1,$2}' zz1
5.2 内建变量
awk常用内置变量:$1、$2、NF、NR、$0
$1:代表第一列
$2:代表第二列以此类推
$0:代表整行
NF:一行的列数
NR:行数
示例一
awk 'NR==2' /etc/passwd //打印第二行,不加print也一样,默认就是打印
awk -F: 'NR==2{print $1}' /etc/passwd 打印第二行的第一列
awk -F: '{print $NF}' /etc/passwd //打印最后一列
awk -F: '{print "当前行有"NF"列"}' zz
awk -F: '{print "第"NR"行有"NF"列"}' /etc/passwd //第几行有几列
5.3 BEGIN END 运算
逐行执行开始之前执行什么任务,结束之后再执行什么任务,用BEGIN、END
BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
END一般用来做汇总操作,仅在读取完数据记录之后执行一次
5.3.1 awk的运算
如果不用引号awk就当作一个变量来输出了,所以不需要加$了
awk 'BEGIN{x=10;print x+1}' BEGIN在处理文件之前,所以后面不跟文件名也不影响
awk 'BEGIN{print 2.5+3.5}' //小数也可以运算
awk 'BEGIN{print 3*4}'
^和**都是幂运算
5.3.2 模糊匹配
模糊匹配,用~表示包含,!~表示不包含
awk -F: '/root/' /etc/passwd
#如果后面有具体打印多少列就没法省略print了
5.3.3 关于数值与字符串的比较
比较符号:== != <= >= < >
5.3.4 逻辑运算
&& 和 || 是逻辑运算符,用于组合多个条件并控制程序流程。
&& 要求所有条件都为真时才为真,否则为假。
|| 只要有一个条件为真就为真,全为假时才为假。
5.3.5 BEGIN END 流程
其他内置变量的用法FS(输入)、OFS、NR、FNR、RS、ORS
FS:输入字段的分隔符 默认是空格
OFS:输出字段的分隔符 默认也是空格
FNR:读取文件的记录数(行号),从1开始,新的文件重新重1开始计数
RS:输入行分隔符 默认为换行符
ORS:输出行分隔符 默认也是为换行符
awk 'BEGIN{FS=":"}{print $1}' pass.txt //在打印之前定义字段分隔符为冒号
5.4 awk高级用法 if语句
awk的if语句也分为单分支、双分支和多分支
awk -F: '{if($3<10){print $0}}' /etc/passwd //第三列小于10的打印整行