Shell脚本三剑客之Sed和Awk

目录

前言

一、文本三剑客之sed

1.1 sed 介绍

1.2  sed 工作流程

1.3  sed 工作原理

1.4 sed命令常见用法

1.4.1  语法结构

1.4.2  常见的选项

1.4.3  常见的操作

1.5  sed用法示例

1.5.1  输出符合条件的文本(p 表示正常输出)

1.5.2  删除符合条件的文本(d) 

1.5.3  替换符合条件的文本  

 1.5.4  迁移符合条件的文本

 1.5.5  使用脚本编辑文件

1.5.6 分组操作

1.5.7  直接修改文件内容   【 i 】

二、awk

2.1  awk常见用法

2.2 工作原理

2.3  awk  内置变量

2.4   用法示例

2.4.1  awk  基本用法

2.4.2 awk常用内置变量

2.4.3  通过管道、双引号调用 Shell 命令

2.4.4  BEGIN、END

2.4.5  模糊匹配

2.4.6    关于数值与字符串的比较

2.4.7   其他内置变量的用法

2.4.8  调用函数getline

2.4.9   awk的  if语句

2.4.10 awk 也可用于for,while,数组

三、总结


前言

Linux中最重要的三个命令在业界被称为“三剑客”,它们是awk,sed,grep。熟练使用这三个工具可以提升运维效率。这章内容重点讲解sed 和awk 的功能。

一、文本三剑客之sed

1.1 sed 介绍

sed 即 Stream EDitor,是行编辑器

Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快

sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。sed 也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于 Shell 脚本中,用以完成各种自动化处理任务。

1.2  sed 工作流程

sed 的工作流程主要包括读取、执行和显示三个过程。

读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。

执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。

显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。

在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

1.3  sed 工作原理

工作原理:

读入新的一行内容到缓存空间;

从指定的操作指令中取出第一条指令,判断是否匹配pattern;

如果不匹配,则忽略后读的编辑命令,回到第2步继续取出下一条指令;

如果匹配,则针对缓存的行执行后续的编辑命令;完成后,回到第2步继续取出下一条指令;

当所有指令都应用之后,输出缓存行的内容;回到第1步继续读入下一行内容;

当所有行都处理完之后,结束;

1.4 sed命令常见用法

通常情况下调用sed命令有两种格式,如下所示。
其中,"参数"是指操作的目标文件,当存在多个操作对象时用,文件之间用逗号" ,"分隔;而 scriptfile表示脚本文件,需要用"-f"选项指定,当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件。

1.4.1  语法结构

sed [选项] '操作' 参数

sed [选项] -f scriptfile 参数

1.4.2  常见的选项

选项

作用

-e或 --expression=

表示用指定命令或者脚本来处理输入的文本文件

-f 或 --file=

表示用指定的脚本文件来处理输入的文本文件

-h 或 --help

显示帮助

-n、--quiet 或 silent

表示仅显示处理后的结果

-i.bak

直接编辑文本文件

-r,-E

使用扩展正则表达式

-s

将多个文件视为独立文件,而不是单个连续的长文件流

1.4.3  常见的操作

"操作"用于指定对文件操作的动作行为,也就是sed的命令。通常情况下是采用的"[n1 [,n2] ]"操作参数的格式。n1、n2是可选的,代表选择进行操作的行数,如操作需要在5~20行之间进行,则表示为"5,20动作行为”。

参数

作用

a

增加,在当前行下面增加一行指定内容

c

替换,将选定行替换为指定内容

d

删除,删除选定的行

i

插入,在选定行上面插入一行指定内容

            p

打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII 码输出。其通常与"一n"选项一起使用

s

替换,替换指定字符

y

字符转换

1.5  sed用法示例

1.5.1  输出符合条件的文本(p 表示正常输出)

输出所有内容,等同于cat   test.txt

输出3~5行

输出所有奇数行,n 表示读入下一行资料

输出所有偶数行,n 表示读入下一行资料

输出第 1~5 行之间的奇数行(第 1、3、5 行)

直接显示第二行内容 

输出第 10 行至文件尾之间的偶数行

以上是 sed 命令的基本用法,sed 命令结合正则表达式时,格式略有不同,正则表达式以“/”包围。例如,以下操作是 sed 命令与正则表达式结合使用的示例。

输出包含the 的行

输出从第 4 行至第一个包含 the 的行

输出包含the 的行所在的行号,等号(=)用来输出行号

输出以数字结尾的行

 输出包含单词wood 的行,\<、\>代表单词边界

1.5.2  删除符合条件的文本(d) 

下面命令中 nl 命令用于计算文件的行数,结合该命令可以更加直观地查看到命令执行的结果。

删除第 3 行

删除第 3~5 行

删除包含 cross 的行,原本的第 9 行被删除;

如果要删除不包含 cross 的行,用!符号表示取反操作, 如'/cross/!d' 

  删除以小写字母开头的行

删除以"."结尾的行 

删除所有空行

注 意 : 若 是 删 除 重 复 的 空行 , 即 连 续 的 空 行 只 保 留 一 个 , “cat -s test.txt”。 

1.5.3  替换符合条件的文本  

在使用 sed 命令进行替换操作时需要用到 s(字符串替换)、c(整行/整块替换)、y(字符转换)命令选项,常见的用法如下所示。

将每行中的第一个the 替换为 THE

 将每行中的第 2 个 l 替换为 L

将文件中的所有o 删除(替换为空串)

在每行行首插入#号

 在每行行尾插入字符串EOF

将包含the 的所有行中的 o 都替换为 O

插入符合条件的行使用-i  表示在行的前面插入一个新行

 使用-i.bak 可以使要编辑的文本进行备份

 1.5.4  迁移符合条件的文本

在使用 sed 命令迁移符合条件的文本时,常用到以下参数.
H:复制到剪贴板;
g、G:将剪贴板中的数据覆盖/追加至指定行;
w:保存为文件;
r:读取指定文件;
a:追加指定内容。具体操作方法如下所示。
I,i : 忽略大小写

案例:

将包含the 的行迁移至文件末尾,    {;}用于多个操作

将第 1~5 行内容转移至第 7 行后 

 将包含the 的行另存为文件 out.txt

将文件/etc/hostname 的内容添加到包含 the 的每行以后

在第 3 行后插入一个新行,内容为New

在第 3 行后插入多行内容,中间的\n 表示换行 

 在包含the 的每行后插入一个新行,内容为 New

 1.5.5  使用脚本编辑文件

使用 sed 脚本将多个编辑指令存放到文件中(每行一条编辑指令),通过“-f”选项来调用

例如执行以下命令即可将第 1~5 行内容转移至第 16 行后。

方法一:sed 命令   sed '1,5{H;d};16G' test.txt    //将第 1~5 行内容转移至第 16 行后

方法二:脚本方法:将多个编辑指令存放到文件中(每行一条编辑指令),通过“-f”选项来调用

1.5.6 分组操作

当我们需要对一行数据进行多次操作的时候我们可以使用{}进行分组 

 当我们运行多个命令时也可以使用选项  -e  来表示

注:-e 可以将多个命令连接起来,也可以将多个编辑命令保存到文件中,通过 -f 指定文件,以完成多个处理操作。 

1.5.7  直接修改文件内容   【 i 】

在每一行的开头插入#号,直接修改原文件

将每一行的开头#号删除,直接修改原文件 

编写一个脚本,用来调整vsftpd 服务配置,要求禁止匿名用户,但允许本地用户(也允许写入)。

二、awk

在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚本,完成各种自动化配置任务。

20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk,之所以叫AWK 是因为其取了三位创始人 Alfred  Aho, Peter   Weinberger 和  Brian  Kernighan  的 family  name 的首字符。

2.1  awk常见用法

通常情况下 awk 所使用的命令格式如下所示,其中,单引号加上大括号“{}”用于设置对数据进行的

处理动作。awk 可以直接处理目标文件,也可以通过“-f”读取脚本对目标文件进行处理。

格式:

awk 选项 '模式或条件 {编辑指令}' 文件 1 文件 2 „         //过滤并输出文件符条件的内容

awk -f 脚本文件 文件 1 文件 2 „          //从脚本中调用编辑指令,过滤并输出内容

前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或者 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。

    在使用 awk 命令的过程中,可以使用逻辑操作符“&&”,表示“与”, “||”表示“或”,“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别 表示加、减、乘、除、取余和乘方。

awk 从输入文件或者标准输入中读入信息,与 sed 一样,信息的读入也是逐行读取的。

不同的是 awk 将文本文件中的一行视为一个记录,而将一行中的某一部分(列)作为记录中的一个字段(域)

为了操作这些不同的字段,awk 借用 shell 中类似于位置变量的方法, 用**$1、$2、$3„顺序地表示行(记录)中的不同字段**。另外 awk 用$0 表示整个行(记录)

不同的字段之间是通过指定的字符分隔

awk 默认的分隔符是空格

awk 允许在命令行中用“-F 分隔符”的形式来指定分隔符

2.2 工作原理

逐行读取文本,默认以空格为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模

式或着条件执行编辑命令。

awk 命令对/etc/passwd 文件的处理过程图:

2.3  awk  内置变量

awk 包含几个特殊的内建变量(可直接用):

变量

解释

FS

指定每行文本的字段分隔符,默认为空格或制表位(tab)

NF

当前处理的行的字段个数

NR

当前处理的行的行号(序数)

$0

当前处理的行的整行内容

$n

当前处理行的第 n 个字段(第 n 列)

FILENAME

被处理的文件名

RS

数据记录分隔,默认为\n,即每行为一条记录(\n表示回车)

2.4   用法示例

2.4.1  awk  基本用法

输出所有内容

或者  awk '{print $0}' shuiguo.txt //输出所有内容,等同于 cat   shuiguo.txt

以冒号作为分割符,显示出第五列的内容

  注:awk默认把这一行当做一列,因为没有被空格分隔,awk默认以空格或tab键分隔

打印出第1和第3列

注:显示一个空格,空格需要用双引号引起来,如果不用引号默认以变量看待,如果是常量就需要双引号引起来

用制表符作为分隔符输出

 定义多个分隔符,只要看到其中一个都算作分隔符

2.4.2 awk常用内置变量

$1:代表第一列
$2:代表第二列以此类推
$0:代表整行
NF:一行的列数
NR:行数

打印包含root的整行内容

打印包含root的行的第一列和第六列

打印每一行的列数

显示行号  使用NR参数

 显示出每行的行号和内容

 打印第二行

 打印第二行的第一列

打印最后一列

 打印总行数   END 表示汇总的意思

打印文件最后一行

显示出文件第几行有几列

2.4.3  通过管道、双引号调用 Shell 命令

操作命令放在{}中

管道符号前面的命令输出的内容交给管道符号后面的命令处理

结合正则表达式,正则表达式同样要被/包围

调用的shell命令需要用""引起来

{}中多个命令之间也能过;分隔

调用wc -l 命令统计使用bash的用户个数(双引号之间直接调命令"wc -l")等同于 grep -c “bash$” /etc/passwd

 统计以冒号分隔的文本段落数,END{ }语句块中,往往会放入打印结果等语句

 查看当前内存使用百分比

 网卡的ip、流量

2.4.4  BEGIN、END

逐行执行开始之前执行什么任务,结束之后再执行什么任务

BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
END一般用来做汇总操作,仅在读取完数据记录之后执行一次

 如果不用引号awk就当作一个变量来输出了,所以不需要加$了

 注:BEGIN在处理文件之前,所以后面不跟文件名也不影响

BEGIN亦可以进行运算

先写’BEGIN{x=0}; ;END{print x}’ ,然后再写中间的匹配// 以/bin/bash结尾 ,因为/有其他匹配的意思,要加转义符号\ ,最后再加{x++},转到下一行

扩展:

BEGIN语句块在awk开始从输入流中读取行之前被运行,这是一个可选的语句块,比方变量初始化、打印输出表格的表头等语句通常能够写在BEGIN语句块中。

END语句块在awk从输入流中读取全然部的行之后即被运行。比方打印全部行的分析结果这类信息汇总都是在END语句块中完毕,它也是一个可选语句块。

pattern语句块中的通用命令是最重要的部分,它也是可选的。假设没有提供pattern语句块,则默认运行{ print },即打印每个读取到的行。awk读取的每一行都会运行该语句块。

这三个部分缺少任何一部分都可以

2.4.5  模糊匹配

用~表示包含,!~表示不包含

模糊匹配,只要有ro就匹配上

匹配结尾不是nologin的行可以使用  ! 取反操作

2.4.6    关于数值与字符串的比较

比较符号:==      !=       <=       >=      <       >

打印出第五行的内容

 进行精确匹配  一定是root

打印出行号小于5的行

打印出第3列大于等于1000的行,以冒号作为分隔符 

 逻辑运算    &&(表示且)    ||   (表示或)

打印出第3列小于10或大于1000的行

打印出行号4到9的行

 打印1-200之间所有能被7整除并且包含数字7的整数数字

2.4.7   其他内置变量的用法

FS、OFS、NR、FNR、RS、ORS

FS:输入字段的分隔符 默认是空格
OFS:输出字段的分隔符 默认也是空格

NR :  当前处理行的行号,从1开始
FNR:读取文件的记录数(行号),从1开始,新的文件重新重1开始计数


RS:输入行分隔符  默认为换行符
ORS:输出行分隔符  默认也是为换行符

在打印之前定义字段分隔符为冒号

 OFS定义了输出时以什么分隔,$1$2中间要用逗号分隔,因为逗号默认被映射为OFS变量,而这个变量默认是空格

 使用FNR的行号可以在追加当有多个文件时,分别列出每个文件的行号数,新的文件都是从1开始的,而NR是列出的行号数是从1开始,不会分别列出各个文件

 RS:指定以什么为换行符,这里指定是冒号,你指定的肯定是原文里存在的字符

把多行合并成一行输出,输出的时候自定义以空格分隔每行,本来默认的是回车键

2.4.8  调用函数getline

定义引用变量

 awk直接定义变量并引用

 调用函数getline,读取一行数据的时候并不是得到当前行而是当前行的下一行

显示奇偶数行

2.4.9   awk的  if语句

awk的if语句也分为单分支、双分支和多分支

单分支为if(){}
双分支为if(){}else{}
多分支为if(){}else if(){}else{}

第三列小于10的打印整行

第三列小于10的打印第三列,否则打印第一列

2.4.10 awk 也可用于for,while,数组

写一个while 循环,来测定行数,去除上面地9行内容,得到分区数

案例:$1=$1是用来激活$0的重新赋值,也就是说字段$1...和字段数NF的改变会促使awk重新计算$0的值,通常是在改变OFS后而需要输出$0时这样做

案例:数组

 

awk 'BEGIN{a[0]=10;a[1]=20;print a[1]}'
awk 'BEGIN{a[0]=10;a[1]=20;print a[0]}'
awk 'BEGIN{a["abc"]=10;a["xyz"]=20;print a["abc"]}'
awk 'BEGIN{a["abc"]=10;a["xyz"]=20;print a["xyz"]}'
awk 'BEGIN{a["abc"]="aabbcc";a["xyz"]="xxyyzz";print a["xyz"]}'
awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a){print i,a[i]}}' 

三、总结

1. sed工具除了调用文件或脚本执行命令,否则命令都需要加上' ' 符号

即:调用 sed 命令有两种格式

sed[选项] '操作' 参数
sed [选项] -f scriptfile 参数
其中,“参数”是指操作的目标文件,当存在多个操作对象时用,文件之间用逗号“,”分隔;

而 scriptfile 表示脚本文件,需要用“-f”选项指定,当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件

-n选项在符合条件输出和结合正则表达式的时候使用

{}用于奇数行和偶数行的筛选或者奇数行和偶数号的其他操作

sed 命令结合正则表达式时,格式略有不同,正则表达式以“/”包围

使用sed删除命令时,nl 命令用于计算文件的行数,结合该命令可以更加直观地查看到命令执行的结果,而不使用-n

2. sed操作指令置于’'中,awk比sed多一个{}

sed[选项] '操作' 参数
awk 选项 '模式或条件 {编辑指令}' 文件 1 文件 2

 

w,who,whoami,who am i

w 显示已经登录的用户及正在进行的操作
who 显示已经登录的用户名、终端名称、登录时间及登录IP
whoami 显示当前用户的用户名
who am i 显示登录系统的时候的用户名,即使已经切换到其他用户也显示登录时的用户
一般输出关于段,列的信息使用awk,其他的使用sed或grep更加方便

awk  输出的奇偶行都使用绝对路径
sed   输出的奇偶行都使用相对路径

使用awk调用shell命令,统计数量时,n是个变量,可自定义
若没有定义n的初始值,则n=0

awk判断条件中双引号之间的内容,如果有特殊符号不需要使用转义符

FS在{}中间使用,F在{}外面使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值