7 模式动作和变量

7.1 模式元素

模式元素主要有如下几种:

/regular expression/        一个正则表达式
expression                  一个单表达式
begpat,endpat               逗号分割的2个模式

BEGIN                       开始模式
END                         结束模式
BEGINFILE                   数据预处理
ENDFILE                     数据后处理操作
empty                       空,默认匹配所有行

7.1.1 正则表达式作为模式

/foo|bar|baz/  { buzzwords++ }
END            { print buzzwords, "buzzwords seen" }

7.1.2 算数表达式作为模式

awk '$1 == "li" { print $2 }' mail-list

7.1.3 BEGINFILE和ENDFILE

这2个模式算是awk提供的钩子函数吧 , BEGINFILE在我们处理文件之前执行, 我们可以在这个模式内部写判断文件权限, 预处理数据工作,ENDFILE这个模式在我们处理完毕文件的时候执行,可以完成后续的工作,比如我们生成一个脚本文件,可以在这里设置后续权限问题的。

7.2 使用SHELL变量

shell的变量和awk的变量是不一样的。想在awk中使用shell的变量可以考虑如下方法:

[root@centos74 test]$ var1="abc"
[root@centos74 test]$ awk -v var1=$var1 'BEGIN{print var1}'
abc

7.3 动作

通常情况下匹配一个模式,都要采取对应的动作。默认的动作是打印。

7.4 控制语句

控制语句是动作的一种。awk中的控制和c基本一样。使用起来也是非常方便的。

7.4.1 if

样例:

if (x % 2 == 0)
    print "x is even"
else
    print "x is odd"

7.4.1 while

样例:

awk '
{
    i = 1
    while (i <= 3) {
        print $i
        i++
    }
}' inventory-shipped

7.4.1 do-while

样例:

{
    i = 1
    do {
        print $0
        i++
    } while (i <= 10)
}

7.4.1 for

样例1:

awk '
{
    for (i = 1; i <= 3; i++)
        print $i
}' inventory-shipped

样例2:

for (i in array)
    do something with array[i]

7.4.1 switch

样例:

while ((c = getopt(ARGC, ARGV, "aksx")) != -1) {
    switch (c) {
    case "a":
        # report size of all files
        all_files = TRUE;
        break
    case "k":
        BLOCK_SIZE = 1024       # 1K block size
        break
    case "s":
        # do sums only
        sum_only = TRUE
        break
    case "x":
        # don't cross filesystems
        fts_flags = or(fts_flags, FTS_XDEV)
        break
    case "?":
    default:
        usage()
        break
    }
}

7.4.1 break

样例:

# find smallest divisor of num
{
    num = $1
    for (divisor = 2; divisor * divisor <= num; divisor++) {
        if (num % divisor == 0)
            break
    }
    if (num % divisor == 0)
        printf "Smallest divisor of %d is %d\n", num, divisor
    else
        printf "%d is prime\n", num
}

7.4.1 continue

样例:

BEGIN {
    for (x = 0; x <= 20; x++) {
        if (x == 5)
            continue
        printf "%d ", x
    }
    print ""
}

7.4.1 nextfile

这个和next类似。 只不过next是去处理下一个记录。 nextfile是出去下一个文件。

7.4.1 exit

这个语句设定退出码的。

样例:

BEGIN {
    if (("date" | getline date_now) <= 0) {
        print "Can't get system date" > "/dev/stderr"
        exit 1
    }
    print "current date is", date_now
    close("date")
}

7.5 预定义的变量

7.5.1 内建控制变量

FIELDWIDTHS             各个字段的宽度
FPAT                    各个字段的模式
FS                      字段分隔符
IGNORECASE              是否忽略大小写,默认是是大小写敏感的
OFS                     输出字段分隔符
ORS                     输出记录分隔符
RS                      记录分隔符,默认是行,就是一行几个记录

7.5.2 内建传递变量

ARGV        命令行参数
ARGC        命令行参数个数
ERRNO       错误号
FILENAME    当前的文件名
FNR         当前的文件记录号
NF          当前记录的字段个数
NR          当前记录数
PROCINFO    这个是一个数组,存储一些进程信息。

7.5.3 使用ARGC和ARGV

样例:

[root@centos74 test]$ awk 'BEGIN {
for ( i=0; i<ARGC;i++)
print ARGV[i]
}' inventory-shipped mail-list
awk
inventory-shipped
mail-list

Attention

我们的语句不是参数。第一个参数是awk命令本身的。