正则表达式之awk

目录

awk简介

基本格式

awk的工作过程

工作原理

awk的基本格式

内置变量

基本打印法

奇偶行打印

awk运算

getline的工作过程

BEGIN打印模式:

处理过程

对字段进行处理打印:

-v的用法:变量赋值

BEIGIN模式指定

条件判断打印:

awk的三元表达式与精准筛选用法

awk的精准筛选

awk的分隔符用法

指定输出的分隔符:

awk中定义数组打印

检测运行机制

实例引用

简单的日志分割

取小数点几位和取整数

统计磁盘总共使用容量

统计内存

监控硬盘


awk简介

在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,

默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。

以空格做为分隔符,多个空格他会自动压缩成一个

AWK信息的读入也是逐行指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理.

1、按照命令找指定的行 2、找到的行 打印,操作 awk默认的操作就是打印

可以在无交互 的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚本,完成各种自动化配置任务。

基本格式

awk ' <pattern><action><input-file>'

           操作符    怎么干    处理对象

awk的工作过程

  • 第一步:执行BEGIN{action;… }语句块中的语句

  • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
  • 第三步:当读至输入流末尾时,执行END{action;…}语句块

BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,

比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中

END语句块在awk从输入流中读取完所有的行之后即被执行,

比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

pattern语句块中的通用命令是最重要的部分,也是可选的。

如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

工作原理

sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个“字段”然后再进行处理,

且默认情况下字段的分隔符为空格或 tab 键。

awk 执行结果可以通过 print 的功能将字段数据打印显示

awk的基本格式

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

-F :  “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符

-v :   var=value 变量赋值

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

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

用逗号指定连续的行,用 || 指定不连续的行。&&表示”且“。

awk {print $1,$2,$3}

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

内置变量

符号说明
$0

当前处理的行的整行内容 打印所有

$n

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

NR

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

NF

当前处理的行的字段个数。$NF代表最后一个字段

FS

列分割符。指定每行文本的字段分隔符,输入内容的分隔符,

默认为空格或制表位。与"-F"作用相同 用-F可以不加单引号 -F:,用FS必须用=""

OFS

输出内容的列分隔符

FILENAME

被处理的文件名

RS

行分隔符。awk从文件中读取资料时,

将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是"\n"

基本打印法

[root@localhost ~]# awk ''
#什么都不写  空没有效果
[root@localhost kyio]# awk '{print}'
11
11
22
22
[root@localhost opt]# awk '0{print}' test1.txt

[root@localhost opt]# awk '1{print}' test1.txt
two one one
twotwo
three three
four



0和1放置{ }前,能够起到限制打印内容的作用(默认为"1"),如果为0,就不打印内容
[root@shell 99]# awk '{print $0}' 1.txt    #$0,代表整行内容;awk是逐行读取处理,配合$0,就是打    
                                               印所有内容
1123  hell world
231
34
1111

$1只取第一列,可以对行切片,输出列
[root@shell 99]# awk '{print $1}' 1.txt
1123
231
34
1111

[root@shell 99]# awk '{print NR}' 1.txt    #打印行号,告诉我们有几行;
1
2
3
4

[root@shell 99]# awk '{print NR,$0}' 1.txt    #不仅打印行号,还把每行对应的内用一起展示,
                                                比sed展示的内容更直观
1 1123  hell world
2 231
3 34
4 1111

[root@shell 99]# awk 'NR==3{print}' 1.txt    #指定打印出第三行的内容
34

[root@shell 99]# awk 'NR==3,NR==4{print}' 1.txt    #打印3-5行的内容
34
1111

[root@shell 99]# awk 'NR==1;NR==4{print}' 1.txt    #打印第一行和第四行
1123  hell world
1111

[root@shell 99]# awk '(NR>=2)&&(NR<=4){print}' 1.txt    #正则的表达方式,打印2-4行的内容
231
34
1111

奇偶行打印

[root@localhost opt]awk 'NR%2==0{print}' test1.txt #打印偶数行

[root@localhost opt]awk 'NR%2==1{print}' test1.txt #打印奇数行

awk运算

[root@localhost home]# awk 'BEGIN{print 100+200}'
300

[root@localhost home]# awk 'BEGIN{print 10.2+20.3}'
30.5

[root@localhost home]# awk 'BEGIN{print 10.2*20.3}'
207.06

[root@localhost home]# awk 'BEGIN{print 10.2/20.3}'
0.502463

[root@localhost home]# awk 'BEGIN{print 10.2-20.3}'
-10.1

[root@localhost ~]# awk 'BEGIN{print 32}'  #^和都是幂运算
9

[root@localhost ~]# awk 'BEGIN{print 2^3}'
8

getline的工作过程

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

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

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

awk '{getline;print $0}' test1.txt #相当于打印了偶数行

awk '{print $0;getline}' test1.txt #相当于打印了奇数行

[root@localhost opt]# awk '{getline < "test1.txt"; print $0 > "test2.txt";}' test1.txt
#使用重定向把test1输出给test2

[root@localhost opt]# ls | awk '{getline line; print $0, line;}'
test1.txt test2.txt
#把ls的输出传递给getline函数,
line是变量 把ls的内容输出给变量,然后打印出结果,如果无内容,不做任何操作
文本内容匹配过滤打印:

BEGIN打印模式:

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

处理过程

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

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

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

[root@localhost opt]# awk 'BEGIN{x=1};{x++};END{print x}' test1.txt
10

对字段进行处理打印:

[root@localhost opt]# head -n5 /etc/passwd |awk  -F: '{print $1}' #已冒号为分割,打印第一列
root
bin
daemon
adm
lp

[root@localhost opt]# head -n5 /etc/passwd |awk  -F: '{print $2}' #已冒号为分割,打印第二列
x
x
x
x
x

-v的用法:变量赋值

[root@localhost home]# fs=":";awk -v FS=$fs -v OFS="+" '{print $1,$3}' /etc/passwd
#fs的是:然后使用-v给FS赋值=:,输入的时候FS是:,-v给OFS赋值输出的时候变量为+,然后打印第一列和第三列

root+0
bin+1
daemon+2
adm+3
lp+4
a=3
b=4

num=$(awk -v a="$a" -v b="$b" 'BEGIN{print a + b}')
把shell的变量传给awk.

[root@localhost ~]#awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd
root==0
bin==1
daemon==2
adm==3
lp==4
sync==5

[root@localhost ~]#echo $PATH | awk -v RS=':' '{print $1}'
#默认就是换行输出,不需要改
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin

BEIGIN模式指定

[root@shell 99]# head -n5 /etc/passwd|awk 'BEGIN{FS=":"};{print $5}'
root
bin
daemon
adm
lp
###---BEGIN模式在awk执行前改变分隔符,执行过程中,以“:”分割,打印指定内容

条件判断打印:

awk -F: '$3>500{print $0}' /etc/passwd
#uid大于500的

awk -F: '!($3>10){print $0}' /etc/passwd
#取反,uid小于10的行,所有列

awk -F: '{if ($3>500){print $0}}' /etc/passwd
#使用了if语句,内部条件(),外部条件{},整个加{}作为一条语句执行,相当于嵌套语法

awk的三元表达式与精准筛选用法

awk的三元表达式继承了java的用法,格式与Java相似

格式:

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

awk -F: '{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd|sed -n '1,6p'
比较passwd文件中以":"为分割的第三个和第四个字段的大小,

max=($3>=$4)?$3:$4:这将变量 max 设置为输入行字段 3 和 4 之间的最大值。
? : 运算符是 if-else 语句的简写,因此此行等效于 if ($3 >= $4) { max=$3 } else { max=$4 }
取比较结果的最大值,赋值给变量max,并且输出max行的所有内容,然后打印其中的1-6行;

awk的精准筛选

字符说明

$n(> < ==)

用于对比数值

$n~"字符串"

代表第n个字段包含某个字符串

$n!~"字符串"

代表第n个字段不包含某个字符串

$n=="字符串"

代表第n个字段为某个字符串

$n!="字符串"

代表第n个字段不为某个字符串

$NF

代表最后一个7字段

实例

输出第七个字段包含“bash”所在行的第一个字段和最后一个字段
awk -F: '$7~"bash" {print $1,$NF}' /etc/passwd

输出第七个字段不包含“nologin”所在行的第一个字段和最后一个字段
awk -F: '$7!~"nologin" {print $1,$NF}' /etc/passwd

指定第六个字段为/home/dn,第七个字段为/bin/bash,输出满足这些条件所在行的第一个和最后一个字段
awk -F: '($6=="/home/dn")&&($7=="/bin/bash"){print $1,$NF}' /etc/passwd


[root@localhost ~]# awk -F: '$7!="/bin/bash" {print $0}' /etc/passwd  #取反
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

awk的分隔符用法

RS 指定行分隔符

awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录,

而awk一次仅读入一条记录进行处理。内置变量RS的预设值是"\n" 也就是换行。

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

echo $PATH | awk 'BEGIN{RS=":"};{print NR,$0}' ---以":"分割,分割后逐行打印内容和行号

指定输出的分隔符:

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

对于输出时改变分隔符,我们常用到tr,awk,它们都可以实现在输出内容改变原本的分隔符

tr改变分隔符输出

[root@shell 99]# echo a b c d|tr " " ":"
a:b:c:d

awk改变输出分隔符

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

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

awk中定义数组打印

[root@shell 99]# awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[1]}'
20
#awk中的数组形成遍历

[root@shell 99]# awk 'BEGIN{a[0]=10 ; a[1]=20 ; a[2]=30;for(i in a)print i,a[i]}'
0 10
1 20
2 30
#在awk中打印变量不需要加$


cat test3.txt
aaa
aaa
bbb
ccc
aaa
bbb
aaa
awk '{a[$1]++};END{for(i in a){print i,a[i]}}' test3.txt  #在awk中打印变量不需要加$

检测运行机制

原理:a[$1]初始为0,a[$1]++后即为1

而这里awk中的a[$1]++最终的值是由test2.txt文本内容有多少行决定的,awk本身就是编程语言,不要按照shell来

文本逐行读取完毕后再执行END中的命令

awk会按行读取文件test2.txt的内容,然后逐个单词存储到数组a中。

每个单词都作为数组a的索引,所以每个单词都对应一个值,初始值为0。

读取文件的第一行,单词为 aaa,此时a[aaa]为0,执行 a[$1]++ 后,a[aaa]变成1。

读取文件的第二行,单词为 aaa,此时a[aaa]为1,执行 a[$1]++ 后,a[aaa]变成2。

读取文件的第三行,单词为 bbb,此时a[bbb]为0,执行 a[$1]++ 后,a[bbb]变成1。

读取文件的第四行,单词为 ccc,此时a[ccc]为0,执行 a[$1]++ 后,a[ccc]变成1。

读取文件的第五行,单词为 aaa,此时a[aaa]为2,执行 a[$1]++ 后,a[aaa]变成3。

读取文件的第六行,单词为 bbb,此时a[bbb]为1,执行 a[$1]++ 后,a[bbb]变成2。

读取文件的第七行,单词为 aaa,此时a[aaa]为3,执行 a[$1]++ 后,a[aaa]变成4。

最终,数组a中的元素值变成:a[aaa]=4,a[bbb]=2,a[ccc]=1。

实例引用

简单的日志分割

awk '{print $1, $7, $9}' /var/log/messages

在这个命令中,我们使用单引号将awk命令的操作包含起来。

$1、$7和$9是awk的内置变量,分别表示每行日志文件中的第1、第7和第9个字段。

通过使用print命令,我们将这些字段分别打印出来,以空格分隔。

最后,我们指定日志文件的路径/var/log/messages,awk会自动对文件中的每行进行处理并输出结果。

只分割前两行内容的第一个和第四个字段

awk 'NR<={print $1,$4}' /var/log/messages

取小数点几位和取整数

result=$(awk 'BEGIN{printf "%.2f", 2.3312.542}') #取小数点2位result=$(awk 'BEGIN{printf "%.F", 2.3312.542}') # 不取小数点,只取整数

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

1 www.kgc.com

2 mail.kgc.com

3 ftp.kgc.com

4 linux.kgc.com

5 blog.kgc.com

cat file.txt | awk -F '[ .]+' '{print $2}' >> host.txt

统计磁盘总共使用容量

df | tail -n +2 | grep -v tmpfs | awk '{sum+=$4} END{print "磁盘可用容量:"sum/1024/1024"G"}'

统计/etc下文件总大小

ls -l /etc | awk '/^-/{sum+=$5} END{print "文件总大小:"sum/1024"M"}'

CPU使用率

top -b -n 1

-b 告诉 top 以批处理模式运行,没有交互界面,这意味着它将输出结果到控制台一次,然后退出。

-n 1 指定 top 在退出之前应运行的迭代次数。在这种情况下,它只运行一次。

us 表示用户空间占用 CPU 百分比,sy 表示内核空间占用 CPU 百分比

[root@localhost network-scripts]# sum=$(top -b -n 1 | grep -w st |awk '{print $2+$4}')

[root@localhost network-scripts]# echo $sum

3.1

统计内存

#使用量

memory_used=$(free -m | grep "Mem:" |awk '{print $3 }')

#总计

memory_total=$(free -m | grep "Mem:" |awk '{print $2 }')

#打印内容:

echo '当前内存的使用量'$memory_used

echo '当前内存的总量'$memory_total

#计算百分比

z=$(echo "scale=2;${memory_used}/${memory_total}*100"|bc)

echo $z

b=$(echo $z | awk -F '.' '{print $1}')

echo $b

echo "当前的使用占比:${b}%"

if [ $b -lt 90 ]

then

echo "内存的使用量正常:${b}%

else

echo "内存的使用量为:"$b"大于90%,请注意!"

fi

监控硬盘

[root@localhost home]# df -h | grep -w centos-root | awk '{print $5}' | tr -d "%"

16%

[root@localhost home]# a=$(df -h | grep -w centos-root | awk '{print $5}') | tr -d "%"

[root@localhost home]# echo $a

16%

[root@localhost home]# b=$(echo "$a" | sed 's/%//g')

[root@localhost home]# echo $b

16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值