awk的流程控制,函数这一块,楼主以前没玩过,今天看了下,确实很有用。

看了一下awk的条件判断和循环和C语言的差不多,在这里就简单的mark下

条件判断

格式

if (expression)

{  action

   .

   .

}

else if (expression)

{   action

    .

    .

}

else

{

  action

  .

  .

}

注意:上面的{}的位置随便放在啥地方都OK,当action只有一个的时候,可以不加{}

if和else放在同一行的时候,用分号隔开

if (expression) action1;else action2

如果条件表达式expression的值为真(非零或非空),就执行相应操作。条件表达式中可能包含算术运算符,关系操作符,或布尔操作符

条件操作符

条件操作符(?:)和C语言中的条件操作符一样。

格式:
expr?action1:action2

常用方式:

a=(x==y)1:2

循环

和C语言中一样,三种形式

while循环

while (condition){

    action

    .

}


do-while循环

do{

    action

    .

}while (condition)

注意:do循环至少执行一次循环体,然后再根据条件判断是否执行

for 循环

for (set_counter;test_counter;increment_counter)

{

    action

    .

}

set_counter:设置计数器的初值

test_counter:描述在循环开始时要测试的条件

increment_counter:每次在循环的底部递增计数器,且恰好在重新测试test_counter之前

注意:

1.循环和条件判断一样,当只有一个action的时候,{}可以不要。

2.注意一下循环中经常会用到i++和++i,这两个在单独使用的时候没啥区别。当和别的运算符结合使用的时候则有区别

如i=1;x=i++,表示先把i的值赋给x,然后i++,得到x的值为1,i的值为2。

而i=;x=++i,则是先i++,再把i++之后的值付给x,得到x的值为2,i的值为2

数组

1.awk的数组类似于C语言的数组形式,awk的关联数组类似于C语言中map容器,类似python的字典,以(key/value)的形式存储

2.相对于C语言的有一维数组,多维数组。awk较为简单了,只有一维数组。但是awk提供了一种方法来模拟多维数组,这是后话了

3.awk中我们不用声明数组,只需要为数组指定标识符,向数组中赋值就OK了

4.C语言可以如下,a[3]={1,2,3}初始化数组,awk不能这么做滴,只能类似这么做for (i=1;i<=3;i++) {a[i]=i}

OK,下面看看数组吧

数组形式

array[subscript] = value

看个例子,以NR为下标,$2为value加入数组。。然后在END例程中遍历打印数组

awk(二)流程控制,数组_action

关联数组

其实在awk中所有的数组都是关联数组,和咱们传统脑子里的数组不同的是,关联数组的下标既可以是数字也可以是字符串。   其实在awk中存储的时候,不管是数字还是字符串都是以字符串的形式存储的

为什么叫关联数组呢,关联是谁和谁之间的关联?

关联其实就是咱们数组中的元素,下标和value存在一定的联系,咱们可以通过下标找到value。

相对于C语言中的数组,像a[1],a[2],a[3],这些值在内存中是顺序存储的,我们查找的时候也可以这么顺序的去查找。

而关联数组,的存储则是无序的,散列的,我们查找value值的时候,是通过下标和value之间的映射关系来查找的。

数组遍历

for (item in array)

    print item,array[item]

成员测试

if (item in array)

    print yes

举个小例子,看看数组的使用

测试文件

lixc boy
liss girl


代码

awk '
BEGIN {FS = "\t";OFS = "\t"                #设置输入输出字段分隔符
    printf("Enter a glossary term:") 
}
FILENAME == "glossary" {                   #匹配文件名glossary
    entry[$1] = $2                         #$1为下标,$2为value,写入数组
    next                                   #该例程匹配到,则跳过下面的例程,读入下一行记录
}
$0 ~ /^(quit|[qQ]|exit|[Xx])$/ {exit}      #匹配退出条件

$0 != ""{                                 
    if ($0 in entry)                       #测试成员是否存在于数字中
    {
        print entry[$0]
    }
    else
        print $0 "not found"

}
{
    printf("Enter another glossary term (q to quit):")
}
'  glossary -                             # "-"   是从终端输入

执行

awk(二)流程控制,数组_表达式_02


用split()函数创建数组

和python中的split()有一点点类似,常用与从字段中提取子字段

用法

n = split(string,array,separator)

string:待分解到名字为array数组的输入字符串

array:数组名,数组的下标从1开始,一直到n

separator:指定的分隔符,可为字符,正则表达式,和字段的分解方式相同。如果不指定分隔符,则默 认使用FS的分割方法

n:返回的array数组的长度。

来个小例子,把01/05/2014或01-05-2014类型的时间改为01 05,2014类型

代码

awk '
BEGIN {
    listmonths = "January,February,March,April,May,June,"       
    listmonths = listmonths "July,August,September,"         #使用字符串连接的功能
    listmonths = listmonths "October,November,December"
    split(listmonths,month,",")                              #生成数组
}
$0 != ""{                                                    #匹配输入不为空的行
    sizeOfArray = split($1,date,"/")                         #以"/"为分隔符,分割数组
    if (sizeOfArray == 1)                                    #判读,是否分割成功
        sizeOfArray = split($1,date,"-")                     #不成功,则以"-"分割
    if (sizeOfArray == 1)                                    #再判断
        exit                                          #不成功,说明输入不是"//"或"--"形式
    date[1] += 0
    print month[date[1]],date[2]","date[3]
}'

执行结果

awk(二)流程控制,数组_C语言_03


删除数组元素

delete array[subscript]

多维数组

awk不支持多维数组,只是用下标来模拟多维数组。

如:awk[3,2]=10   可以理解为第3行第2列,value为10。

但是下标3,2在存储的时候,其实还是一个下标。。3,2使用系统变量SUBSEP连接起来。

SUBSEP的默认值为\034。。那么3,2实际存储形式为3\342

成员测试

if ((i,j) in array)

系统变量数组

ENVIRON和ARGV

ENVIRON

环境变量数组,下标为环境变量的名字。

查看该数组的详细内容

awk 'BEGIN{for (env in ENVIRON) print env"------"ENVIRON[env]}'

ARGV

命令行参数数组,不包括脚本本身和其他任何awk的指定选项。参数个数可以用ARGC获得,数组的第一个下标为0,最后一个下标为ARGC-1


这东西在BEGIN例程中用的挺好的

在主循环例程中,就有点小问题了

awk(二)流程控制,数组_action_04