shell - sed命令和awk命令

一.sed 的高级用法

sed 中除了模式空间,还另外支持保持空间,利用此空间,可以将模式空间中的数据,临时保存至保持空间,从而后续接着处理,实现更为强大的功能。

常见命令:

选项含义
P(大)打印模式空间开端至\n内容,并追加到默认输出之前
N读取匹配到的行的下一行追加至模式空间
n读取匹配到的行的下一行覆盖至模式空间
G保持空间取出的内容追加至模式空间
g保持空间取出的数据覆盖至模式空间
H模式空间中的内容追加至保持空间
h模式空间中的内容覆盖至保持空间
x把模式空间中的内容与保持空间中的内容进行互换
d删除模式空间中的行
D如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环,如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环

操作:

原理:

打印偶数行的几个方法:

seq 10 | sed -n 'n;p'

seq 10 | sed -n '2~2p'

seq 10 | sed '1~2d'

seq 10 | sed -n '1~2!p'

二.awk 

1.简介

AWK是一种优良的文本处理工具。它不仅是 Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

有多种版本:

  • AWK:原先来源于 AT & T 实验室的的AWK

  • NAWK:New awk,AT & T 实验室的AWK的升级版

  • GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容

2.awk

2.1 工作原理

前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个"字段"然后再进行处理,且默认情况下字段的分隔符为空格或tab键,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。awk 执行结果可以通过 print 的功能将字段数据打印显示。

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

awk 后面接两个单引号并加上大括号{ }来设置想要对数据进行的处理操作,awk 可以处理后续接的文件,也可以读取来自前个命令的标准输出。

2.2 命令的基本格式

awk [选项] '模式条件{操作}' 文件1 文件2...

注意:

① 一定是单引号: '模式或条件{操作}'

② {}外指定条件,{}内指定操作

③ 内建变量不能使用双引号括起来,不然系统会把它当成字符串

选项:

-v定义变量
-F指定分隔符

常见内置变量

内置变量作用
NR当前处理的行的行号(序数)
NF当前处理的行的字段个数
FS

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

与 “ -F ” 作用相同

OFS输出内容的列分隔符
RS行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n"
$0当前处理的行的整行内容
$n当前处理行的第n个字段(第n列)
FILENAME被处理的文件名

2.3 基本打印用法

2.3.1 打印文章所有内容
[root@localhost ~]#awk '{print}' /etc/passwd

注意:0 和 1 放置 {} 前,能够起到限制答应的作用(默认为“1”

[root@localhost ~]#awk '{print $0}' /etc/passwd

2.3.2 打印行内容及其行号
[root@localhost ~]#awk '{print NR}' /etc/passwd

[root@localhost ~]#awk '{print NR,$0}' /etc/passwd

2.3.3 指定行和指定行范围打印
[root@localhost ~]#awk 'NR==3{print}' /etc/passwd


[root@localhost ~]#awk 'NR==3,NR==5{print}' /etc/passwd


[root@localhost ~]#awk 'NR>=3&&NR<=5{print}' /etc/passwd

2.3.4 奇偶行打印
[root@localhost ~]#awk 'NR%2==0{print}' /etc/passwd
#打印偶数行

[root@localhost ~]#awk 'NR%2==1{print}' /etc/passwd
#打印奇数行

2.3.5 奇偶打印特殊方式-- getline

getline工作过程:

(1)当getline左右无重定向符号(“<”)或者管道符号(“|”)时,awk首先读取的是第一行,而getline获取的是是光标跳转至下一行的内容(也就是第二行)

原因:getline运行之后awk会改变NF,NR,$0,FNR等内部变量,所以此时读取$0的行号不再为1,而是2

注意:

FNR:awk当前读取的记录数,其变量值小于等于NR,(比如说当读取完第一个文件后,读取第二个文件,FNR是会从0开始进行,而NR不会)。因此读取两个或两个以上的文件,NR==FNR,可以 判断是不是在读取第一个文件

(2)当getline左右有管道符号或重定向符时,getline则作用定向输入文件,由于文件是刚打开,并没有被awk读入一行,而只是getline读入,所以getline返回的是文件的第一行,而不是跳转至一行输入

打印偶数行

[root@localhost etc]#seq 10 |awk '{getline;print $0}'

打印奇数行

[root@localhost etc]#seq 10 |awk '{print $0;getline}'

2.3.6 文本内容匹配过滤打印
[root@localhost ~]#awk '/^root/{print}' /etc/passwd

[root@localhost ~]#awk '/bash$/{print}' /etc/passwd



2.4 BEGIN打印模式

2.4.1 BEGIN

 格式:awk 'BEGIN{...};{...};END{...}' 文件

 处理过程:
1、在 awk 处理指定的文本之前,需要先执行 BEGIN{...} 模式里的命令操作

2、中间的 {...}  是真正用于处理文件的命令操作

3、在 awk 处理完文件后才会执行 END{...}模式里的命令操作。END{ } 语句块中,往往会放入打印结果等语句。

 awk是从c语言中继承到Linux,所以在BEGIN模式中变量x,可以直接运用,无需"$"声明获取变量值

[root@localhost etc]#awk 'BEGIN{x=0};{x++};END{print x}' /etc/passwd

2.4.2 BEGIN 计算

在 awk 处理指定的文本之前,需要先执行 BEGIN{...} 模式里的命令操作

2.5 对字段进行处理打印

2.5.1 指定分隔符打印字段

普通指定方式

[root@localhost etc]#awk -F ':' '{print$1}' /etc/passwd |head -n5

BEGIN模式指定

[root@localhost etc]#awk 'BEGIN{FS=":"};{print $1}' /etc/passwd |head -n5

2.5.2 条件判断打印

正向判断打印:

[root@localhost ~]#awk -F: '$3>=1000{print $3,$1}' /etc/passwd

#先用 -F指定分隔符为":" ,文件以":"分割的第三列为uid,uid大于1000的打印第三列和第一列,也就是uid和用户

判断取反打印:

[root@localhost ~]#awk -F: '!($3<=1000){print $3,$1}' /etc/passwd

还可以直接进行 if 语句判断打印:

[root@localhost ~]#awk -F: '{if($3>=1000){print $3,$1}}' /etc/passwd

2.5.3 提取 df 里面数字
[root@localhost ~]#df |awk '{print $5}'|tail -n +2 |tr -d %

或者

[root@localhost ~]#df |awk -F"[ %]+" '{print $5}'|tail -n +2

#[ %] 一个字符  看到空格和%,都当作分隔符  + 一个以上

[root@localhost ~]#df |awk -F"[[:space:]]+|%" '{print $5}'|tail -n +2




2.5.4 取ip地址
[root@localhost ~]#ifconfig ens33|awk '/netmask/{print $2}'

[root@localhost ~]#ifconfig ens33|sed -rn '2s/.*inet (.*)  netmask.*/\1/p'

3.awk 的三元表达式与精准筛选

3.1 三元表达式

3.1.1 java和shell中的三元表达式

java中:

(条件表达式)?(A表达式或者值):(B表达式或者值)

解释:

条件表达式成立(为真)时,会取冒号前面的值A。  - 条件表达式不成立(为假)时,会取冒号后面的值B。  

shell中:

[ 条件表达式 ] && A || B

解释:

条件表达式成立(为真)时,会取||前面的值A。  - 条件表达式不成立(为假)时,会取||后面的值B。

3.1.2 awk三元表达式的应用

格式:awk     '(条件表达式)?(A表达式或者值):(B表达式或者值)'

[root@localhost ~]#awk -F: '{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd |sed -n '1,6p'


#比较passwd文件中第三列和第四列的大小
去他们结果较大的值,赋于变量max 并且输出max及其所在行的全部内容

3.2 awk 精准筛选

筛选方法:

$n (><==)用于对比数值
$n~"字符串"代表第n个字段,包含某个字符串的作用
$n!~"字符串"代表第n个字段,不好含某个字符串的作用
$n=="字符串"代表第n个字段为某个字符串的作用
$n!="字符串"代表第n个字段不为某个字符串的作用
$NF代表最后一个字段

操作:

① 输出第七个字段包含“bash”所在行的第一个字段和最后一个字段

[root@localhost ~]#awk -F: '$7~"bash"{print $1,$NF}' /etc/passwd

② 输出第七个字段不包含“nologin”所在行的第一个字段和最后一个字段

[root@localhost ~]#awk -F: '$7!~"nologin"{print $1,$NF}' /etc/passwd

③ 指定第六个字段为/home/xyl   ,第七个字段为/bin/bash,输出满足这些条件的所在行

[root@localhost ~]#awk -F: '($6=="/home/xyl")&&($7=="/bin/bash"){print $0}' /etc/passwd

4.awk的分隔符

4.1 RS 指定分隔符

awk 从文件中读取资料时,将根据 RS 的定义把资料切割成许多条记录, 而 awk 一次仅读入一条记录进行处理。内置变量 RS 的预设值是"\n"。

 但是也可以在使用 BEGIN 模式在操作前进行行分隔符的改变。

[root@localhost ~]#echo $PATH |awk 'BEGIN{RS=":"};{print NR,$0}'

4.2 指定输出的分隔符

4.2.1 FS 输入时的列分隔符

在里面定义:

在外面定义:

4.2.2 OFS 输出内容的列分隔符($n=$n 用于激活,否则不生效,n且必须存在)

[root@localhost ~]#echo A B C D |awk '{OFS="|";print $0;$1=$1;print $0}'
A B C D
A|B|C|D

[root@localhost ~]#awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd

4.2.3 NF 代表字段的个数
[root@localhost ~]#awk -F: '{print $NF}' /etc/passwd

[root@localhost ~]#df | awk  '{print $(NF-1)}'

$(NF-1)  倒数第二列

4.2.4 NR 显示行号
[root@localhost ~]#awk -F: '{print NR}' /etc/passwd

打印行号为2的

[root@localhost ~]#ifconfig ens33|awk 'NR==2'

[root@localhost ~]#ifconfig ens33|awk 'NR==2{print $0}'

[root@localhost ~]#ifconfig ens33|awk 'NR==2{print}'

2-5行

[root@localhost ~]#ifconfig ens33|awk 'NR>=2&&NR<=5{print}'

不要第1行

[root@localhost ~]#ifconfig ens33|awk 'NR!=1{print}'

4.2.5 FNR 分开显示行号

4.2.6 FILENAME 显示当前处理文件的名字

4.2.7 tr改变分隔符输出

格式:tr  原分隔符   改变后的分隔符

4.2.8 awk 改变输出分隔符

直接修改输出分隔符:

[root@localhost ~]#echo a b c d|awk '{OFS=":" ;$1=$1; print $0}'

BEGIN模式中修改输出分隔符:

[root@localhost ~]#echo a b c d|awk 'BEGIN{OFS=":"};{$1=$1; print $0}'

5.awk 结合数组运用

5.1 awk中定义数组打印

[root@localhost ~]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[1]}'
20

[root@localhost ~]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[0]}'
10

此外,awk中的数组还能形成遍历

[root@localhost ~]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a)print i,a[i]}'

5.2 awk打印文件内容去重统计

5.2.1 去重打印数组
[root@localhost ~]#x=(10 10 10 20 30 20 30 20 40 10 30 10)
[root@localhost ~]#echo ${x[@]}|awk -v RS=' ' '!a[$1]++'
10
20
30
40

5.2.2 处理文件去重统计

原理:将文件的字段内容变为定义的数组下标,对其进行匹配读取累加(只有遇到完全一致的才会累加),此时重复的次数在for循环的作用下成为了数组对应下标的元素,所以输出该下标和元素(就等同于输出重复的字段内容  以及统计的重复次数)

6.关系表达式

关系表达式结果为“真”才会被处理

真:结果为非0值,非空字符串

假:结果为空字符串或0值

n=0 第一行为假,不打印

小编别:

奇偶数行

seq 5 |awk 'i=!i'    奇数行

#第1行 i=0  假=!假    真   打印
#第2行 i=1  真=!真   假   不打印
....

seq 5 |awk -v i=1 'i=!i'    偶数行
seq 5 |awk '!(i=!i)'        偶数行

7.awk脚本

8.小问题

8.1 提取下面的字段中的 IP地址和时间

法一:
[root@localhost data]#cat text.txt |sed -nr 's/(.*) - - \[(.*) \+.*/\1  \2/p'


法二:
[root@localhost data]#cat text.txt |awk -F"[[ ]" '{print $1,$5}'


[root@localhost data]#cat text.txt |awk -F"[[ ]+" '{print $1,$4}'

8.2 提取host.txt主机名再放回host.txt文件

[root@localhost data]#cat host.txt |awk -F"[ .]" '{print $2}' >> host.txt


[root@localhost data]#cat host.txt |cut -d "." -f1 |tr -d "[0-9 ]"  >> host.txt


[root@localhost data]#cat host.txt |sed -nr 's/[0-9] (.*)\.kgc\.com/\1/p'  >> host.txt



方法一:

方法二:

方法三:

8.3 统计 /etc/fstab 文件中每个文件系统类型出现的次数

[root@localhost data]#cat /etc/fstab |grep -v "^#"|grep -v "^$"|awk '{print $3}'|sort|uniq -c

8.4 统计单词个数

[root@localhost data]#cat /etc/fstab |grep -Eo "\b[[:alpha:]]+\b"|wc -l

8.5 提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字

8.6 查出/tmp/的权限,以数字方式显示

[root@localhost data]#stat /tmp|awk -F"[(/]" 'NR==4{print $2}'

8.7 查出用户UID最大值的用户名、UID及shell类型

[root@localhost data]#awk -F: '$3>=1000{print $3,$1}' /etc/passwd |sort -nr

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值