详解awk(三)变量、流程控制、数组解析与实例

目录

一、awk变量

1.1 awk中变量的分类

1.2 内建变量

1.3 字段变量

1.4 所能对变量进行的运算

二、awk流程控制

2.1 语句组

2.2 if-else

2.3 while

2.4 for

2.5 do-while

2.6 break、continue

2.7 next、exit

三、awk数组

3.1 awk数组是关联数组

3.2 实例1:倒序输出

3.3 实例2:遍历数组

3.4 实例3:操作数组

3.5 如何判断是否存在某个index

3.6 获取数组里面是否有某个value

3.7 删除数组元素

3.8 字符串切割和存储


一、awk变量

1.1 awk中变量的分类

awk中表达式可以使用的变量有以下三类

  • 用户定义的:变量名可以由字母、下划线和数字组成。
  • 内建变量:变量名都以大写字母组成。
  • 字段变量:变量名的形式为$number。

而在awk程序中,变量的类型是不需要声明的,awk程序会自动根据上下文判断变量的类型。未初始化的变量的值默认为空或0。

除了字段变量外,引用内建变量和用户自定义变量都不需要符号“”$。

 

1.2 内建变量

变量

意义

是否会被重置

默认值

ARGC

命令行参数的个数

ARGV

命令行参数数组

FILENAME

当前输入的文件名

每当有一个新的文件被读取,该值就会被重置

NF

当前记录的字段数

每当awk从输入流中读取新的一行时就会被重置

FS

输入流的字段分割符

" " 空格

NR

当前已读取的记录数

FNR

文件总的的记录数

OFMT

数值的输出格式

".6g"

OFS

输出字段分割符

ORS

输出记录分割符

"\n"

RS

输入流的记录分割符

RLENGTH

被函数match匹配的字符串长度

RSTART

被函数match匹配的字符串的开始

随着match的调用而被重置

SUBSEP

下标分割符

"\034"

简单的几点说明:

内建变量可以理解为是awk程序为了方便的进行统计和字段、记录切割操作而默认提供的变量。不需要定义即可直接使用。一般都在BEGIN设置。

内建变量和普通变量一样,可以在PROGRAM中的任何地方修改,使用起来更加灵活。

 

1.2.1 ARGV与ARGC

ARGV是一个数组,内部元素的值是命令行参数的值。可以通过ARGV[INDEX]的形式调用各命令行参数。其中:

ARGV[0]是awk程序名

往后各元素的值则是命令行参数的值。

最后一个元素是awk程序作用的文件名。

ARGC是ARGV count,统计了ARGV的元素个数。

[tyson@Tyson Lee testawk]$ awk 'BEGIN{print ARGC,ARGV[0],ARGV[1],ARGV[2],ARGV[3],ARGV[4]}' a="var1" b="var2" c="var3" text.txt 
5 awk a=var1 b=var2 c=var3 text.txt

ARGV是可以自行修改的

[tyson@Tyson Lee testawk]$ awk 'BEGIN{ARGV[5]="newVar";print ("newARGC="ARGC".we can use ARGV[5],ARGV[5]="ARGV[5])}' a="var1" b="var2" c="var3" text.txt 
newARGC=5.we can use ARGV[5],ARGV[5]=newVar

 

1.3 字段变量

什么是字段?-对每一条记录用字段分割符分割开的是一个个字段。

什么是字段变量?-对字段进行引用的变量就是字段变量(和shell的位置参数类似)。例如:

  • $0:对当前记录进行整体引用
  • $1:对当前记录的第一个字段进行引用
  • $2:对当前记录的第二个字段进行引用
  • $NF:对当前记录的最后一个字段进行引用
  • 可以进行算数运算,$(NF-1):对当前记录的倒数第二个字段进行引用
  • 每一行的字段数量可以不同,通常上线为一百。

字段变量和普通变量一样,可以被用在patter或action的表达式中,可以被重新赋值。当然被若添加或删除了字段变量则相应的变量如$0、ARGV、ARGC、NF等都会发生改变。

[tyson@Tyson Lee testawk]$ awk 'BEGIN{FS=":";OFS="\t"};$4>=500{$4="system_user"};$4<500{$4="normal_user"};{$8="hi";print $1,$4,$8}' /etc/passwd|grep tyson
tyson   system_user     hi
tyson1  system_user     hi

 

1.4 所能对变量进行的运算

算数运算、赋值、三目运算、逻辑运算、匹配运算、关系运算、拼接运算、单目运算、自增自减运算等。

其中比较重要的有:

逻辑运算(只有0或1这两种值,运算符两边的称为操作数)

exp1 $$ exp2

exp1 || exp2

三目运算符(条件表达式)

exp1?exp2:exp3

其他不再赘述

 

二、awk流程控制

在awk的PROGRAM中的action部分中,可以使用和C语言类似的语法,因此同样会涉及到流程控制的问题。主要的问题是在命令行中和在自行指定的awk文件中的写法有区别(其实就是单行书写和多行书写的不同规范问题)。但是begin不能再流程控制语句中,因为按照定义,BEGIN这个模式只能够被识别一次。

 

2.1 语句组

#多行模式
statement1
statement2
statement3
#单行模式
statement1;statement2;statement3

 

2.2 if-else

#多行模式
{
if (expression)
    statements
else
    statements2
}
#单行模式
{if (expression) statements1;else statements2}

 

2.3 while

while (expression) {statement1;statement2;statement3}

 

2.4 for

for  {expression1;expression2;expression3}
等价于 expression1;while(expression2){statments;expression3]
#三个表达式都是可省的,exp2省略是永真循环

 

2.5 do-while

do statments while (expression)
#先执行do,用while判断,然后循环执行do

 

2.6 break、continue

中断距离break或continue最近的for、while或do-while的这一次循环,选择退出循环或执行下一轮循环。

 

2.7 next、exit

控制的是用于读取输入行动作的程序循环。

next:抓取下一输入行并按顺序执行PROGRAM部分的(判断是否匹配+执行action)。

exit:整个awk程序不会再读取下一行并直接开始执行模式END的ACTION块,若exit在模式END的ACTION块中出现则直接退出程序。(默认退出状态码为0,可以通过exit expression指定退出状态码)。

 

三、awk数组

awk内数组与数组元素都不需要事先声明,也不需要说明数组中有多少个元素(length)。具有直接使用、自动扩展的特性。

被提及时则数组元素被创建,元素默认初始值是空。

awk中的数组是关联数组。

awk中数组的下表可以是字符串或数值。

  • 字符串下标是多功能的数组下标,arr[1]与arr["1"]是同一个元素(因为“1”的字符串值是1),但是通常不这么使用。
  • 字符串下标“01”与字符串下标“1”对应的值并不相同

 

数组具体说明

8

"foo"

""

30

Value

0

1

2

3

Index

元素对应的value会占内存空间,下标是不占空间的。

 

3.1 awk数组是关联数组

何为关联数组?

  • 每个数组都是对(索引及其对应的数组元素值)的集合
  • 索引不一定是字数,可以是数字或字符串。
  • 索引可以是乱序的,不一定递增。
  • 关联数组中,索引可以是整数也可以是字符串。

 

3.2 实例1:倒序输出

[tyson@Tyson Lee testawk]$ cat text.txt
SR     8649 275  Asia
Canada   3852 25   North_America
China    3705 1032 Asia
USA      3615 237  North_America
Brazil   3286 134  South_America
India    1267 746  Asia
Mexico   762  78   North_America
France   211  55   Europe
Japan    144  120  Asia
Germany  96   61   Europe
England  94   56   Europe
[tyson@Tyson Lee testawk]$ awk '{x[NR]=$0};END{for(i=NR;i>0;i--){print x[i]}}' text.txt 
England  94   56   Europe
Germany  96   61   Europe
Japan    144  120  Asia
France   211  55   Europe
Mexico   762  78   North_America
India    1267 746  Asia
Brazil   3286 134  South_America
USA      3615 237  North_America
China    3705 1032 Asia
Canada   3852 25   North_America
SR     8649 275  Asia

NR表示目前已读取的行数,{x[NR]=$0} 表示对每一行都执行这个对数组赋值的操作,也就是按顺序将每一行录入到数组。

当PROGRAM执行到END时,NR已经是整个文件的行数了,所以END中的内容则是倒叙输出。

 

3.3 实例2:遍历数组

遍历数组的方式是:

for (name in array){statements}

name每次赋予的值是index的值。

[tyson@Tyson Lee testawk]$ cat text.txt 
SR     8649 275  Asia
Canada   3852 25   North_America
China    3705 1032 Asia
USA      3615 237  North_America
Brazil   3286 134  South_America
India    1267 746  Asia
Mexico   762  78   North_America
France   211  55   Europe
Japan    144  120  Asia
Germany  96   61   Europe
England  94   56   Europe
[tyson@Tyson Lee testawk]$ awk '{pop[$4]+=$2};END{for (name in pop) {print name,pop[name]}}' text.txt 
North_America 8229
Asia 13765
Europe 401
South_America 3286

在这里需要注意的是,若在数组中使用了未定义的变量做下表,例如我未定义Test的值,那么array[Test]的值相当于array[""]。

 

3.4 实例3:操作数组

数组的格式array_name[index]

数组的赋值array_name[1]=val或array_name["string"]=val

数组的引用array_name[1]或array_name["string"]

需要注意的点:

当数组某元素的下标(index)不存在于该数组时,会创建有该下标对应的元素,value为空。这种操作经常导致内存崩溃。

 

3.5 如何判断是否存在某个index

使用index in array表达式用于测试特定的索引所以是否存在,若不存在也不会创建该元素,避免了内存崩溃。

 

3.6 获取数组里面是否有某个value

只能遍历并对比数组的所有元素

 

3.7 删除数组元素

delete array[index]

for (i in array)

delete array[i]

 

3.8 字符串切割和存储

split函数split(str,arr,fs)

str:输入字符串

arr:用来存放切割好的字段的数组

fs:字段分割符

返回值:切割完成后字段的个数。

[tyson@Tyson Lee testawk]$ awk '{split($0,temp_array," ");print temp_array[1];for (i in array){delete temp_array[i]}}' text.txt  
SR
Canada
China
USA
Brazil
India
Mexico
France
Japan
Germany
England
[tyson@Tyson Lee testawk]$ cat text.txt 
SR     8649 275  Asia
Canada   3852 25   North_America
China    3705 1032 Asia
USA      3615 237  North_America
Brazil   3286 134  South_America
India    1267 746  Asia
Mexico   762  78   North_America
France   211  55   Europe
Japan    144  120  Asia
Germany  96   61   Europe
England  94   56   Europe

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值