sed和awk

sed和awk

准备:
一台Rocky Linux9 的虚拟机

sed

sed是一款流编辑工具,用来对文本进行过滤,编辑操作,用于需要对几十个配置文件统一修改。sed一次只读取一行内容,对内容执行某些指令进行处理,然后输出,更适合大数据文件。

sed首先读取文件内容,将读入内容复制到缓冲区(模式空间pattern space),所有指令都是在缓冲区进行,sed根据指令修改后输出结果,默认输出到标准输出

sed基本语法

sed 【选项】 ... {脚本指令} [输入文件] ...

选项:

--version 显示sed版本

--help 显示帮助文档

-n, --quite, --slient 静默输出,默认情况下,sed执行完毕后将自动打印模式空间的内容,这个选项屏蔽自动打印

-e script 允许多个脚本指令被执行

-f script-file 从文件中读取脚本指令

-i, --in-place 直接修改源文件

-r 在脚本指令中使用正则

-s 默认情况下,sed将输入的多个文件名作为一个长的,连续的输入流,而GNU sed 允许把他们作为单独的文件

基本格式规范:

脚本指令常用:a 追加 i 插入 d 删除 s替换

脚本指令基本格式: 【地址】指令

指令可用花括号进行组合,组合后用于同一个地址:

address{

command1

command2

command3

}

eg:从etc下将passwd文件复制到root目录下

bash 复制代码
cp /etc/passwd .
cat passwd

在第二行后面追加一个test1

bash 复制代码
sed '2a test1' passwd

在第三行前追加test2,因为这些操作都是在缓冲中操作的,所有读取源文件会发现没有任何修改

bash 复制代码
sed '3i test2' passwd
cat passwd


将文件中所有bin修改为bash

bash 复制代码
sed 's/bin/bash/g' passwd  # 结尾添加g为所有全部更改,不加只会修改每一行第一个匹配成功的

删除文件中第2,3,4行(第2到4行)内容

bash 复制代码
sed '2,4d' passwd

综合使用:

在第二行后添加test1,第五行前添加test2,将所有的bin替换为bash,删除7,8行

bash 复制代码
sed '{
2a test1
5i test2
s/bin/bash/g
7,8d
}' passwd

也可以单独指定一行使用,如指定修改第三行的daemon为zhangsan,所有的2为45

bash 复制代码
sed 3'{
s/daemon/zhangsan/g 
s/2/45/g
}' passwd

sed正则匹配

因为实际使用中,更多的时候,我们并不知道所需要修改的内容所在行号的,所以需要使用正则匹配区匹配内容然后修改

格式:

sed '/正则/指令' 文件

eg:

在adm下一行添加test3

bash 复制代码
sed '/^adm/a test3' passwd

修改games行所有的0为?号

bash 复制代码
sed '/games/s/0/?/g' passwd

sed地址匹配

1、在sed中通过 开始行~步长 的方式来指定步长操作

eg:从第一行开始每2行后面添加一行test

bash 复制代码
sed '1~2a test' passwd

2、\cregexpc 在\c与c之间进行正则表达式匹配,c字符可以用任意字符代替,但是注意只能为单个字符

eg:

将mail行的8替换为20

bash 复制代码
sed '\cmailcs/8/20/' passwd

3、addr1,addr2 匹配地址1到地址2之间的所有行

eg:将第3行到第6行之间的所有bin替换为bash

bash 复制代码
sed '3,6s/bin/bash/' passwd

4、addr1,+N 匹配操作地址1及后面的N行内容

eg: 将第4行和后面的3行中的bin换为bash

bash 复制代码
sed '4,+3s/bin/bash/' passwd

sed指令与脚本

sed常用指令

指令 功能 指令 功能
s 替换 d 删除
a 追加 i 插入
c 更改 l 打印,可以显示非打印字符
y 按字符转换 = 打印当前行
p 打印 r 读入文件内容
w 保存至文件 q 立刻推出sed脚本

sed脚本

sed脚本也是sh脚本,需要使用sed -f 参数去运行

格式: sed -f 脚本文件 需要修改的文件

eg:

1、编写一个html文件,将其中错误的body换为/body

bash 复制代码
echo '''
<html> 
<title> First Web </title>
<body> This is a html file <body>
</html> ''' > index.html

编写sed脚本,这里第一个是正则匹配包含body的那行,s//第一个空则为修改前面正则匹配的内容,第二个/body \为注释掉后面的/,使其识别为/而不是sed替换里面的/

bash 复制代码
echo '/body/{s//\/body/2}' > sed.sh 

使用sed运行sed脚本

bash 复制代码
sed -f sed.sh index.html

当然,也可以用其他符号来替代/,只要是有3个就行,哪怕是数字,字母,下面就是用a来替换/的作用

2、修改index.html如下,将其中h1h2h3 第一个加上<>变为<h1><h2> <h3>第二个h1h2h3变为</h1></h2><h3>

编写sed脚本,在这里面用&来替代h[1-3],因为是加上<>符号,所以需要添加转译

bash 复制代码
/h[1-3]/{
s//\<&\>/1
s//\<\/&\>/2
}

执行sed脚本

3、从/etc/NetworkManager/system-connections下将ens160.nmconnection文件复制到/root下,把包含id=ens160修改为id=eth0

bash 复制代码
cp /etc/NetworkManager/system-connections/ens160.nmconnection /root

使用sed,命令

bash 复制代码
sed '/^id/c id=eth0' ens160.nmconnection

4、将上面的文件的小写全部修改为大写

编写sed脚本,/y是将后面第一个的所有字符用第二个替换

bash 复制代码
vim sed.sh
/.*/{
//y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
}

如果需要单独换某行:

bash 复制代码
/.*/{
/autoconnect/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
}

5、先读取ens160文件,再读取index.html文件

符号表示在文件最后一行读完后开始读index.html文件。如果不添加符号,会每读一句ens160文件中的内容都输出一遍index.html内容

bash 复制代码
sed '$r index.html' ens160.nmconnection

不加$示例

编写sed脚本,读取1到4行,每一行读完后都读一遍index.html

bash 复制代码
/.*/{
5,$d
r index.html
}

sed高级应用

多行读取Next(N)

Next(N)指令通过读取新的输入行,将其追加至模式空间的现有内容之后,来创建多行模式空间,其中的换行符直接显示为\n,一个N往下多读一行,两个N多读两行

eg:有一个简易的user_info文件:

这个文件需要将Name和Mail同行显示

使用sed命令,这个命令表示,通过匹配文件中的Name字符,当匹配成功时读取当前行和下一行,换行符用\n替代:

bash 复制代码
sed -n '/Name/{N;l}' user_info

多行打印Print(P)

多行打印Print(P)仅输出多行模式空间中的第一部分,直到\n为止

N;l会读取两行作为一行,但因为l会将输出的不显示的字符正常显示,所以会输出读取到的内容,读取到的\n作为字符显示

N;P会将N读取到的内容交由P处理,N读完两行后换行地方有\n结尾有$,P读取到\n就结束了,所以只会输出\n前面的内容

N;p会正常的将N读出的内容输出,其中\n作为换行符正常生效

多行删除Delete(D)

d为删除指令,作用为删除模式空间中的内容并读入新的输入行,如果在d后面有多条指令,则剩下的指令不会执行,而是返回第一条指令对新读入的内容进行处理,多行删除指令D将删除模式空间中的第一个插入的换行符\n前面的内容,不会读入新的输入行,并返回sed脚本的顶端,使剩余的指令可以继续作用于模式空间的其他内容

Hold(h,H)、Get(g,G)

除了模式空间外,还有保持空间(hold space),两者可以互相复制数据,Hold和Get用于两者之间移动数据

Hold(h|H)将模式空间中的内容复制或追加到保持空间

Get(g|G)将保持空间中的内容复制或追加到模式空间

Exchange(x) 交换保持空间和模式空间的内容

eg:如下的文件test.txt

编写sed脚本,将aaa行放入保持空间,然后删除aaa行,在ccc行后面将aaa行取出:

bash 复制代码
/aaa/{
h
d
}
/ccc/{
G
}

AWK

Awk是一种编程语言,用于在Linux/Unix下的对文本和数据进行扫描和处理,数据可以来自标准输入,文件、管道。分为gawk和mawk,其中RedHat使用gawk,Ubuntu使用mawk

AWK工作流程

逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行用户想要的操作,Awk基本结构由模式匹配和处理过程

awk读取文件内容的每一行时,将对比该行是否与给定的模式相匹配,匹配则执行处理过程,否则不对该行做任何处理。若没有处理过程,则显示匹配的行(默认处理为print),若没有匹配模式,则默认所有数据

awk两个特殊的模式:BEGIN和END,他们分别在没有读取任何数据之前和所有数据读取完毕后执行

AWK语法基本格式

gawk [选项] -f program-file [--] file ...

选项:

-F fs 指定以fs作为输入行的分隔符(默认为空格或制表符)

-v var=val,--assign var=val,在执行处理过程前设置一个变量var值为val

-f program-file,--file program-file,从脚本文件中读取awk指令,以取代命令参数中输入处理脚本

-W compat,-W traditional,--compat, --traditional 使用兼容模式运行AWk,GNU扩展选项将会被忽略

-W copyleft,-W copyright,--copyleft,--copyright,输出简短的GNU版权信息

-W dump-variables[=file], --dump-variables[--file]打印全局变量(变量名,类型,值)到文件中,如果没有提供文件名,则自动输出至名为dump-variables的文件中

-W help,-W usage, --help, --usage 显示各个选项的简短描述

AWK语法结构:一个AWK程序包含一系列模式(动作指令)或函数定义,模式可以是BEGIN,END,表达式,用来限定操作对象的多个表达式用逗号分隔,动作指令用{}包裹

eg:

1、通过正则表达式匹配空白行,然后打印Blank Line ,每有一个空白行,打印

一个Blank Line

使用ens160文件

bash 复制代码
awk '/^$/ { print "Blank Line" }' ens160.nmconnection

使用awk脚本执行

bash 复制代码
# awk.sh文件内容
/^$/ {print "Blank Line"}

# 命令行
awk -f awk.sh ens160-nmconnection

2、打印包含系统名的行

bash 复制代码
awk '/PRETTY_NAME/' /etc/os-release

AWK操作指令

1、记录与字段

awk一次从文件读取一条记录,并将记录存储在字段变量0中,记录被分割为字段并存储在1,2,... , NF中(默认空格或制表符分割),内建变量NF记录字段个数

eg:

2、字段分隔符

默认情况用空格或制表符来分隔字段,但可以用-F 来自定义分隔符

eg:

查看passwd文件,里面是使用:作为分隔符的


3、内置变量

变量名 描述
ARGC 命令行参数个数
FILENAME 当前输入文件名称
FNR 当前输入文件的行记录编号,尤其是多个输入文件时有用
NR 输入流的当前行记录编号
NF 当前记录中的字段个数
FS 分隔字符号
OFS 输出字段分隔符,默认空格
ORS 输出记录分隔符,默认换行符\n
RS 输入记录分隔符,默认换行符\n

4、表达式与操作符

表达式由变量、常量、函数、正则表达式、操作符组成,Awk中的变量有字符变量和数字变量。如果Awk中变量未初始化,则初始值为0或空,对字符进行操作时一定要加引号

操作符:

操作符 作用 操作符 作用
+ /= 相除后赋值给变量
- > 大于
* < 小于
/ >= 大于等于
% 取余 <= 小于等于
^ 幂运算 == 等于
++ 自加1 != 不等于
-- 自减1 ~ 匹配
+= 相加后赋值给变量 !~ 不匹配
-= 相减后赋值给变量 &&
*= 相乘后赋值给变量 ||

eg:





高级用法

if条件判断

语法格式1:

if (表达式)

动作1

else

动作2

语法格式2:

if (表达式)动作1;else 动作2

eg:

编写awk.sh输出第三个字段大于60的项

bash 复制代码
{
if ($3 > 60)
print $0
}

awk -F: -f awk.sh passwd


2、while循环

语法格式1:

while (条件)

动作

语法格式2:

do

动作

while (条件)

eg:

3、for循环

for 语法格式:类似于C语言的for循环

for (变量;条件;计数器)

动作

eg:

4、Break和Continue

break跳出循环,终止接下来所有循环

continue跳出当前循环,终止当前循环所有动作,开始下一次循环

eg:

5、函数

(1)rand()产生0-1宅男的浮点类型随机数,但需要通过srand()设置参数,否则每次产生的数都一样,srand可以自己添加随机种子,默认是当前时间作为随机种子,所以如果太快的话输出也是一样的


(2)gsub(x,y,z)

在字符串z中使用字符串y替换与正则表达式x项匹配的所有字符串,z默认$0

(3)sub(x,y,z)

在字符串z中使用字符串y替换与正则表达式x项匹配的第一个字符串,z默认$0

(4)length(z)

计算并返回字符串z的值

(5)getline

从输入中读取下一行内容

相关推荐
码农多耕地呗3 小时前
VMware创建虚拟机
linux·运维·服务器
wggmrlee3 小时前
性能压测-单机
linux
youyudexiaowangzi3 小时前
ubuntu 1604安装组件报错
linux·运维·ubuntu
muls13 小时前
java面试宝典
java·linux·服务器·网络·算法·操作系统
Eric.Lee20213 小时前
python实现pdf转图片png
linux·python·pdf
剑锋所指,所向披靡!3 小时前
linux的目录结构
linux·运维·服务器
我爱学习好爱好爱3 小时前
Ansible变量介绍 vars变量 inventory针对主机设置变量
linux·自动化·ansible
结衣结衣.4 小时前
【Linux】命名管道的妙用:实现进程控制与实时字符交互
linux·运维·开发语言·学习·操作系统·交互
IMPYLH4 小时前
Linux 的 groups 命令
linux·运维·服务器·bash