awk笔记

目录

一、awk简介

二、awk使用

1、awk的命令格式

2、操作和模式

3、awk脚本基本结构

4、awk的工作原理

5、常用使用示例

三、在program中使用变量

1、内置变量

记录分隔符相关变量

数据分割段相关变量

示例

2、用户自定义变量

在脚本中使用用户自定义变量

在命令行中使用变量


一、awk简介

awk的强大之处在于能生成强大的格式化报告。

数据可以来自标准输入、一个或多个文件,或其它命令的输出。

它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。

它在命令行中使用,但更多是作为脚本来使用。

awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。

如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。

awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。下面介绍的awk是以GUN的gawk为例的,在linux系统中已把awk链接到gawk
 

二、awk使用

1、awk的命令格式
Usage: awk [options] -f 'progfile'  file ...
Usage: awk [options] 'program' file ...



options:
	-F : 指明输入时用到的字段分隔符 
	-v var=value :自定义变量
	
program: 
	PATTERN{ACTION STATEMENTS}
    语句之间用分号分隔
2、操作和模式

模式可以是以下任意一个:

/正则表达式/:
	使用通配符的扩展集
	如,/string/ ,表示匹配以string为字符串的行

关系表达式: 
	可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较
	如$2>$1选择第二个字段比第一个字段长的行
	
模式匹配表达式:
	用运算符~(匹配)和~!(不匹配)
	
模式,模式:
	指定一个行的范围。该语法不能包括BEGIN和END模式
	/1/,/10/ 从1到10行
	'NR==1,NR==10' ,从1到10行
	
	
BEGIN:
	让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量
	
END:
	让用户在最后一条输入记录被读取之后发生的动作

操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。

主要有四部份:

	变量或数组赋值

	输出命令

	内置函数

	控制流命令
3、awk脚本基本结构
# 一个awk脚本通常由:
# BEGIN语句块
# 能够使用模式匹配的通用语句块
# END语句块3部分组成,这三个部分是可选的。

awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

任意一个部分都可以不出现在脚本中,脚本通常是被单引号双引号中,例如:

awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename
4、awk的工作原理
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

第一步:执行BEGIN{ commands }语句块中的语句;

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕

第三步:当读至输入流末尾时,执行END{ commands }语句块。
 

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

END语句块:
	在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

pattern语句块:
	是通用命令是最重要的部分,它也是可选的。
	如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。
5、常用使用示例
  • 在脚本中使用多个命令
# 使用多个命令,则在每个命令之间加分号
# 冒号进行分割字段,然后把第一个字段替换为“Description:”,最后打印出整行数据

[ec2-user@aws ~]$ awk -F: '{$1="Description:"; print $0}' file
Description: There is a big dog and a little dog in the park
Description: There is a big cat and a little cat in the park
Description: There is a big tiger and a litle tiger in the park
  • 从文件中读程序命令
# 如果program程序命令过多,可以单独放在一个文件中,然后从文件中读命令。
# 还是以上面为例,把
{
$1="Description:"
print $0
}

# 单独放在一个文件script1中。再用awk处理脚本时,需要用选项 -f 指定脚本程序的位置

[ec2-user@aws ~]$ awk -F: -f script1 file
Description: There is a big dog and a little dog in the park
Description: There is a big cat and a little cat in the park
Description: There is a big tiger and a litle tiger in the park
  • 在处理数据之前运行脚本
# awk默认每次读入一行数据,然后用脚本进行处理。
# 如果想在处理文本之前预处理一些命令,可以用BEGIN关键字指定

[ec2-user@aws ~]$ awk -F: 'BEGIN{print "开始处理..."}{print $2}' file
开始处理...
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
  • 在处理数据后运行脚本
# 用END关键字在处理完所有数据后,再运行善后处理工作

[ec2-user@aws ~]$ awk -F: '{print $2} END{print "处理结束..."}' file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
处理结束...

三、在program中使用变量

变量又分为两种形式:awk内置的变量;用户自定义的变量。

1、内置变量
记录分隔符相关变量
- FS :输入字段分隔符

- OFS:输出字段分隔符
	
- RS:输入记录分割符
	
- ORS:输出字段分隔符

- FIELDWIDTHS:定义数据字段的宽度
数据分割段相关变量
FILENAME: 当前文件名

NR: 表示所有处理文件已处理的输入记录个数

FNR: 文件的当前记录数

NF: 表示数据文件中数据字段的个数,可以通过$NF获取最后一个数据字段

ARGC: 命令行参数个数

ARGV: 命令行参数数组

$0: 这个变量包含执行过程中当前行的文本内容。

$1: 这个变量包含第一个字段的文本内容。

$2: 这个变量包含第二个字段的文本内容。
示例
  • 操作的file文件内容
The dog:There is a big dog and a little dog in the park
The cat:There is a big cat and a little cat in the park
The tiger:There is a big tiger and a litle tiger in the park
  • FS用法
# 用FS指定字段分隔符为“:”,然后用“:”把每行数据分割为两段。

[ec2-user@aws ~]$ awk 'BEGIN{FS=":"} {print $1, $2}' file
The dog There is a big dog and a little dog in the park
The cat There is a big cat and a little cat in the park
The tiger There is a big tiger and a litle tiger in the park

OFS用法

# 用FS指定输入字段分隔符“:”后,每行数据分为两个数据段
# 输出时,用OFS指定两个数据字段用“>”拼接。

[ec2-user@aws ~]$ awk 'BEGIN{FS=":"; OFS=">"} {print $1, $2}' file
The dog>There is a big dog and a little dog in the park
The cat>There is a big cat and a little cat in the park
The tiger>There is a big tiger and a litle tiger in the park

RS和ORS用法

# 默认情况下RS和ORS设置为“\n”
# 表示输入数据流中的每一行作为一条记录,输出时每条记录之间也以“\n”进行分割。

下面以file2文件为例,fiel2文件中内容如下:
Tom is a student
and he is 20 years old

Bob is a teacher
and he is 40 years old

# 默认情况下,每行作为一条记录处理
# 但此种情况下,要把第一行和第二行作为一条记录处理,第三行和第四行作为一条记录处理

[ec2-user@aws ~]$  awk 'BEGIN{RS=""; ORS="\n"; FS="and"; OFS=","} {print $1, $2}' file1 file2
Tom is a student
, he is 20 years old
Bob is a teacher
, he is 40 years old

ARGC和ARGV

# ARGC表示命令行中的参数个数,ARGV是参数数组
# 可见,每处理一行数据时,都是两个参数,第一个是awk本身,第二个是处理的文件名

awk -F: '{print ARGC, ARGV[0], ARGV[1]}' file
2 awk file
2 awk file
2 awk file

NR和FNR

# FNR表示处理文件的当前记录号,NR表示所有处理文件已处理的输入记录个数

[ec2-user@aws ~]$ awk -F: '{print "NR="NR, "FNR="FNR, $2}' file file1
NR=1 FNR=1 There is a big dog and a little dog in the park
NR=2 FNR=2 There is a big cat and a little cat in the park
NR=3 FNR=3 There is a big tiger and a litle tiger in the park
NR=4 FNR=1 
NR=5 FNR=2 

# 注意,不要对NR和FNR加$
# 例如,如果对NR加$,加入NR等于5,实际就是取每条记录的第5个数据字段,实际没有这么多,只能取到空
2、用户自定义变量
在脚本中使用用户自定义变量

建立一个script1的脚本,内容如下:

awk '
BEGIN{
    FS = ":"
    name = "lzj>"
}
{
    $1 = name
    print $0
}' file

运行该脚本 ./script

[ec2-user@aws ~]$ ./script 
lzj> There is a big dog and a little dog in the park
lzj> There is a big cat and a little cat in the park
lzj> There is a big tiger and a litle tiger in the park

# 在脚本中直接定义了一个name变量,在脚本程序中可以直接引用该变量。
# 注意在yaml命令中,赋值语句“=”的前后是不能有空格的
# 但是在awk程序的内部是可以有的,因为awk是一种单独的编程语言。
在命令行中使用变量

首先定义一个script2脚本,其内容为:

BEGIN{
FS = ":"
}
{
    print $n
}

脚本中有一个n的变量,在命令行中传入

[ec2-user@aws ~]$ awk -f script2 n=2 file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

注意一个问题:在命令行中传入的参数,默认在BEGIN是不能获取的,例如
script2脚本改为如下,在BEGIN部分获取n的值:

BEGIN{
FS = ":"
print "请输出第二部分...", n
}
{
    print $n
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值