第八章 awk文本出来工具

第八章 awk文本出来工具

1,简介

1,awk用于在Linux/UNIX下处理文本和数据

2,数据可以来自标准输入,一个或多个文件,或者其他命令的输出

3,支持用户自定义函数和动态正则表达式等。

4,awk有自己的程序设计语言。擅长数据分析及生成报表,对文件内容进行各种排版操作

5,可以通过man awk获取相关功能说明

6,awk是一种过程式编程语言或脚本语言解释器,支持条件判断,数组,循环等功能。

2,工作流程

awk的处理文本和数据的流程方式如下:它逐行扫描文件,从第一行到最后行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕);如果没有指定模式,则所有被操作所指定的行都被处理

image.png

3,工作原理

awk格式:
awk 'BEGIN{commands}  pattern	{commands}  END  {commands}'

1,BEGIN语句在awk开始从输入流中读取之前被执行,这是一个可选的语句块,如变量初始。
2,END语句在awk在处理完所有的文本之后被执行。也是可选的
3,pattern语句中的通用命令是最重要的部分,也是可选的。如果没有改语句,则默认执行print,即打印读取的每一行,awk读取的每一行都会执行改语句块。

#执行步骤:
(1)执行begin{commends}语句块中的语句。
(2)从文件或标准输入(stdin)读取一行,然后执行pattern{commands}语句块,它逐行扫描文件,从第一行至最后一行。
(3)当读至输入流末尾时,执行end{commands}语句块。

4,语法格式

基本语法格式

awk  'pattern'  filename
或
awk  'action'  filename
或
awk  'pattern{action}'  filename

image.png

语法选项实例

1#文件/etc/passwd中匹配root行
[root@localhost ~]# awk '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

2#文件/etc/passwd打印满足条件的第一个字段和第三个字段
[root@localhost ~]# awk -F ":" '{print $1,$3}' /etc/passwd

image.png

1$0表示所有域,$n表示第n个域。默认分隔符是“空格键”或“tab”键。
2,初始时,FS默认为空格。
3,print时的逗号称为输出字段分隔符OFS,OFS默认为空格。
4,awk输出之后,将从文件中获取另一行,并将其放在$0中,覆盖原来的内容;再将新的字符串分割成字段并进行处理,这一过程将持续到所有行处理完成。
3#打印/etc/passwd下所有的用户名
[root@localhost ~]# awk -F: '{print $1}' /etc/passwd

4#打印/etc/passwd下所有的用户名(在第一行)及UID(在第三行)
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd

5,内置变量

awk优于grep和sed的主要原因是支持对记录和字段的处理。

image.png

image.png

FIELDWIDTHS以空格分隔的字段宽度,如果指定此变量,awk将会用指定的宽度替换变量FS指定的分隔符,具体
如下所示。
1#内置变量举例
[root@localhost ~]# cat test1
abcdefasfa
abcdefasfa
abcdefasfa
[root@localhost ~]# awk 'BEGIN{FIELDWIDTHS="2 3 4"}{print $1,$2,$3}' test1
ab cde fasf
ab cde fasf
ab cde fasf

2#FS:输入分隔符,OFS:输出分隔符
[root@localhost ~]# awk 'BEGIN{FS=":";OFS="---"}{print $1,$2}' /etc/passwd

3#$0指的是整行记录
[root@localhost ~]# awk -F":" '{print $0}' /etc/passwd

4#NR指当前文件的总行号递增
[root@localhost ~]# awk -F":" '{print NR,$0}' /etc/passwd /etc/hosts

5#FNR指不递增
[root@localhost ~]# awk -F":" '{print FNR,$0}' /etc/passwd /etc/hosts

6#$NF指最后一个字段的值
[root@localhost ~]# awk -F":" '{print NR,$0,NF,$NF}' /etc/passwd /etc/hosts

7#RS记录分割符(默认是一个换行符),以空格作为分割符
[root@localhost ~]# awk -F":" 'BEGIN{RS=" "}{print $0}' /etc/passwd

8#ORS输出数据中默认输出一条记录的分隔符。以空格作为分隔符,将文件每一行合并为一行
[root@localhost ~]# awk -F":" 'BEGIN{ORS=" "}{print $0}' /etc/passwd

6,模式

image.png

image.png

1#文件b.txt内容
[root@localhost ~]# cat b.txt
yang sheng:is a::good boy!

#以空格作为分隔符,打印出字段数
[root@localhost ~]# awk '{print NF}' b.txt
4
#以冒号为分隔符
[root@localhost ~]# awk -F":" '{print NF}' b.txt
4
#以空格或冒号为分隔符
[root@localhost ~]# awk -F"[ :]+" '{print NF}' b.txt
6

2#a+=5,等价于a=a+5
[root@localhost ~]# awk 'BEGIN{a=5;a+=5;print a}'
10

3#文件/etc/passed中打印出以root开头的行
[root@localhost ~]# awk -F":" '/^root/' /etc/passwd


4#awk判断运算,如果为真则输出?后的内容,如果为假则输出:后面的内容
[root@localhost ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
ok
[root@localhost ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'
err

5#创建一个新的文本文件a.txt
[root@localhost ~]# cat a.txt
2 this is a test
3 Are you like awk
This is a test
10 There are orange,apple,mongo

#打印第一列大于2的行
[root@localhost ~]# awk '$1>2' a.txt
3 Are you like awk
This is a test
10 There are orange,apple,mongo

#打印第一列等于2的行
[root@localhost ~]# awk '$1==2' a.txt
2 this is a test

7,流程控制

if条件语句

#if单分支语句
if	()
语句1
else
语句2
(2)#if嵌套语句
if  (条件表达式)
	{if  (条件表达式)
		语句
	else
		语句
	}
语句    
else
	{if  (条件表达式)
		语句
	else
		语句
	}
语句
#案例:
1#根据UID判断系统中用户时系统用户还是普通用户
[root@localhost ~]# awk -F: '{if ($3<=200) {name="system"} else {name="user"} print $1,name}' /etc/passwd

2#统计系统用户数
[root@localhost ~]# awk -F: '{if ($3>0 && $3<1000){++i}} END{print i}' /etc/passwd
40

while循环

#while循环
while 条件表达式
{语句}
#案例:
1#while循环语法结构脚本
[root@localhost ~]# awk 'BEGIN{i=1;while(i<=10){print i;i++}}'
1
2
3
4
5
6
7
8
9
10

2#文件/etc/passwd以root行开头打印出每个字段
[root@localhost ~]# awk -F: '/^root/{i=1;while(i<=7){print $i;i++}}' /etc/passwd

#do...while循环(至少执行一次)
do
语句
while	(条件表达式)
#案例
#验证do...while循环
[root@localhost ~]# cat c.txt
111 222
333 444 555
666 777 888 999
[root@localhost ~]# awk '{i=1;do {print $i;i++} while (i<=NF)}' c.txt

for循环

#for循环
#数组遍历的方式:
for {变量 in 数组}
{语句}

#固定循环的方式
for (变量;条件;表达式)
{语句}

解读:for语句首先执行初始化语句,然后再检查条件。如果条件为真,则执行语句,然后执行递增或者递减操作。只要条件为真,循环就会一直执行。 每次循环结束都会进行条件检查,若条件为假则结束循环。
#案例
#使用for循环输出数字1~5
[root@localhost ~]# awk 'BEGIN{for (i=1;i<=5;i++){print i}}'
1
2
3
4
5

#使用for循环分别打印每行每列字段
[root@localhost ~]# awk -F: '{for(i=1;i<=NF;i++){print $i}}' /etc/passwd

break,continue,exit

#break命令:中断当前正在执行的循环并跳出当循环外执行下一条语句
#continue命令:从当前位置跳出到循环开始处执行
#exit命令:退出循环
#案例
#当计算的和大于50时,使用break结束循环
[root@localhost ~]# awk 'BEGIN{sum=0; for(i=0;i<10;++i){sum+=i;if(sum>50)break;else print "Sum=",sum}}'

#输出1~20之间的偶数,使用continue语句
[root@localhost ~]# awk 'BEGIN{for(i=1;i<=10;++i){if(i%2==0)print i;else continue}}'
2
4
6
8
10

#当和大于50时结束awk程序
[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<20;++i){sum+=i;if(sum>50)exit(10);else print "sum=",sum}}'
sum= 0
sum= 1
sum= 3
sum= 6
sum= 10
sum= 15
sum= 21
sum= 28
sum= 36
sum= 45

数组

1,数组索引(下标)可以是数字和字符串,一般称作key,并且与对应数组元素的值相关联。

2,awk中的数组称为关联数组。数组元素key和值都放在awk内部程序的某张表中,通常用一定散列算法来存放,所以数组元素并不是按照一定顺序存放的。同理也不是按照顺序打印的,但是我们可以使用管道来达到效果

3,awk中的数组不必提前声明,也不必声明大小,因为它在运行时可以自动地增加或减少。数组元素用0或空字符串来初始化

4,awk中的数组用来从记录中收集信息,可以用于计算总和,统计单词以及跟踪模块别匹配的次数等

5,awk数组结构

image.png

image.png

#数组定义
数组名[下标]=元素值
array_name{string}=value

其中,索引下标可以是数字,也可以是字符
#数组使用
数组名[下标]

#输出数组元素的值
print 数组名[下标]

#遍历数组循环结构
for(变量名 in 数组名){print 数组名[变量名]
#案例
#遍历数组,显示/etc/passwd的root账户
[root@localhost ~]# awk -F: '{username[++i]=$1} END{print username[1] } ' /etc/passwd
root

#遍历数组,显示/etc/passwd的帐户
[root@localhost ~]# awk -F: '{user[i++]=$1} END{for(i in user){print i,user[i]}} ' /etc/passwd

#使用数组统计文件/etc/passwd中各中类型shell的数量
[root@localhost ~]# awk -F: '{shells[$NF]++}END{for(i in shells){print i,shells[i]}} ' /etc/passwd
/bin/sync 1
/bin/bash 5
/sbin/nologin 38
/sbin/halt 1
/sbin/shutdown 1

#统计网站访问状态
[root@localhost ~]# netstat -ant|grep ':80' |awk '{status [$NF]++} END{for(i in status){print i,status[i]}}'

8,函数

1,函数的使用包含两部分:函数的定义与函数调用

  • 函数定义包含 函数名,函数参数,函数体

2,awk分为内建函数和自定义函数

image.png

image.png

#内建函数
#要求统计用户名为4个字符的用户,传统方法为:
[root@localhost ~]#[root@localhost ~]# awk -F: '$1~ /^....$/{count++;print $1}END{print "count is:" count}' /etc/passwd

#使用内建函数length()计算并返回字符串的长度
[root@localhost ~]# awk -F: 'length($1)==4 {count++;print $1}END{print "count is:" count}' /etc/passwd
#自定义函数
function 函数名 (参数表)	{
函数体
}

1,函数名是用户自定义函数的名称。以字母开头,后面可以是数字,字母或下划线的自由组合。awk保留的关键字不能作为用户自定义函数的名称。
2,自定义函数可以接非必要的参数,参数之间用逗号分隔,参数不是必须得,用户也可以定义没有任何输入参数的函数,函数体包含awk程序代码。
案例:#分别返回两个数值中的最大值和最小值。在主函数main中调用这两个函数。
[root@localhost ~]# vim functopn.awk
#返回最小值
function find_min (num1,num2)
{
   if   (num1 < num2)
        return num1
return num2
}
#返回最大值
function find_max(num1,num2)
{
   if   (num1 > num2)
        return num1
return num2
}
#主函数
function main(num1,num2)
{
   #查找最小值
   result = find_min(10,20)
   print  "Min =",result
   #查找最大值
   result = find_max(10,20)
   print  "Max =",result
}
#脚本从这里开始执行
BEGIN {
   main(10,20)
}

#结果
[root@localhost ~]# awk -f functopn.awk
Min = 10
Max = 20
#以下实例实现awk使用外部变量,定义变量“var=bash”,把“Unix”替换成变量“bash”
#在双引号的情况下使用
[root@localhost ~]# var="bash"
[root@localhost ~]# echo "Unix script"|awk "gsub(/Unix/,\"$var\")"
bash script
#打印磁盘使用率大于5%的挂载点
#方法一:定义变量
[root@localhost ~]# df -h |awk '{if (int($5)>"'$i'"){print $6":" $5}}'
/:50%

#方法二:awk的选项-v传递参数
[root@localhost ~]# var=bash
[root@localhost ~]# echo "Unix scripts" |awk -v var="bash" 'gsub(/Unix/,var)'
bash scripts
0
Max = 20
#以下实例实现awk使用外部变量,定义变量“var=bash”,把“Unix”替换成变量“bash”
#在双引号的情况下使用
[root@localhost ~]# var="bash"
[root@localhost ~]# echo "Unix script"|awk "gsub(/Unix/,\"$var\")"
bash script
#打印磁盘使用率大于5%的挂载点
#方法一:定义变量
[root@localhost ~]# df -h |awk '{if (int($5)>"'$i'"){print $6":" $5}}'
/:50%

#方法二:awk的选项-v传递参数
[root@localhost ~]# var=bash
[root@localhost ~]# echo "Unix scripts" |awk -v var="bash" 'gsub(/Unix/,var)'
bash scripts
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值