awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk做大的优势。

语法形式

awk [options] 'script' var=value file(s)

awk [options] -f scriptfile var=value file(s)

1.常用命令选项

-F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:

-v var=value   赋值一个用户定义变量,将外部变量传递给awk

-f scripfile  从脚本文件中读取awk命令

-m[fr] val   对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

 

2.三种方式调用awk及使用

方式一:shell命令行输入命令调用awk,格式为:awk [-F 域分隔符] 'awk程序段' 输入文件。

方式二:将awk程序段插入脚本文件,然后通过awk命令调用它,格式为:awk -f awk脚本文件 输入文件。

方式三:将awk命令插入脚本文件后,执行该脚本./awk脚本文件 输入文件(awk脚本仍以#!/bin/gawk符号开头)。

 

 方式一:awk '/^$/{print "This is blank."}' input,表示一旦读入文件行是空行就打印This is blank。awk由两部分组成,以/符号分隔,^$(是正则表达式是空白行)部分是模式;花括号部分是动作,是打印操作;input是文件名称。

 方式二:awk第二种调用方式,新建source.awk输入/^$/{print "This is blank."},然后调用awk -f source.awk input。

方式三:vim source.awk

#!/bin/awk -f
/^$/{print "This is blank."}
然后执行./source.awk input。

3. 记录和域

    awk认为输入文件是结构化的,awk定义域操作符$来指定执行动作的域,域操作符$后面跟数字或变量来标识域的位置,每条记录的域从1开始编号,$1表示第1个域,$2表示第2个域,$0表示所有的域。

[root@hpf-linux 222]# cat 1.txt 

00 00 0 0 000

11 1 1 1 11 11

2222 2 2 22 2

[root@hpf-linux 222]# awk '{print $1,$2}' 1.txt 

00 00

11 1

2222 2

 默认的分隔符是空格键,使用-F选项来指定输入分隔符(小写-f表示调用awk脚本)。

[root@hpf-linux 222]# awk -F ':' '{print $1 $2}' passwd

rootmailx

binx

daemonx

admx        

[root@hpf-linux 222]# awk -F ':' '{print $1,$2}' passwd

rootmail x

bin x

daemon x

adm x

[root@hpf-linux 222]# awk -F ':' '{print $1"#"$2}' passwd

rootmail#x

bin#x

daemon#x

adm#x

[root@hpf-linux 222]# awk -F ':' 'OFS="@"{print $1,$2}' passwd

rootmail@x

bin@x

daemon@x

[root@hpf-linux 222]# awk -F ':' '{OFS="#";print $1,$2}' passwd 
rootmail#x
root#x
bin#x
daemon#x

从以上五个例子我们可以发现:若在输出域上不加分隔符则不会将输出的内容分开,若用“,”分开则在输出内容会用空格分开,同时我们也可以指定输出分隔符,第一种是用"任意字符"将输出内容分开,第二种是在开头指定输出分割符OFS="任意字符"。

[root@hpf-linux 222]# awk -F ':' '{print $0}' passwd //打印全部域


rootmail:x:0:0:root:/root:/bin/bash


bin:x:1:1:bin:/bin:/sbin/nologin


daemon:x:2:2:droataemon:/sbin:/sbin/nologin


adm:x:3:4:adm:/varrtoooo/adm:/sbin/nologin

 

打印带有root的行并将带root的行的第七段打印出来并添加行号:

[root@hpf-linux 222]# awk -F':' '/root/ {print NR":"$7}' passwd 

1:/bin/bash

11:/sbin/nologin

awk内置变量:

          ARGC        命令行参数个数

          FILENAME    当前输入文档的名称

          FNR        当前输入文档的当前记录编号,尤其当有多个输入文档时有用

          NR         输入流的当前记录编号

          NF         当前记录的字段个数

          FS         字段分隔符

          OFS        输出字段分隔符,默认为空格

          ORS        输出记录分隔符,默认为换行符\n

           RS        输入记录分隔符,默认为换行符\n

也可以以字符串为分隔符打印出来                               
[root@hpf-linux 222]# awk -F'/sbin' '{print $1}' passwd 
rootmail:x:0:0:root:/root:/bin/bash
    
root:x:0:0:root:/root:/bin/bash
          
bin:x:1:1:bin:/bin:
             
daemon:x:2:2:droataemon:
       
adm:x:3:4:adm:/varrtoooo/adm:

打印第七段并将行号列印出来

[root@hpf-linux 222]# awk -F':' ' {print NR":"$7}' passwd 

1:/bin/bash

2:/sbin/nologin

3:/sbin/nologin

4:/sbin/nologin

 查看每一行有多少段

[root@hpf-linux 222]# awk -F':' ' {print NR":"NF}' passwd 

1:7

2:7

3:7

4:7

 5.awk的查找功能

 [root@hpf-linux 222]# awk '/root/' passwd 
 
 rootmail:x:0:0:root:/root:/bin/bash
 
 operator:x:11:0:operator:/root:/sbin/nologin
 
 [root@hpf-linux 222]# awk '/ro+t/' passwd 
 
 rootmail:x:0:0:root:/root:/bin/bash
 
 lp:x:4:7:lp:/var/sprooootool/lpd:/sbin/nologin
 
 operator:x:11:0:operator:/root:/sbin/nologin
 
 [root@hpf-linux 222]# awk '/ro?t/' passwd 

 adm:x:3:4:adm:/varrtoooo/adm:/sbin/nologin

 csa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

 [root@hpf-linux 222]# awk '/root|ftp/' passwd 

rootmail:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

     从以上几个例子及实验可以得出:awk可以实现grep的功能,但是不能给查找的关键字添加颜色,以及在使用扩展正则表达式时可以直接使用,而grep要使用扩展正则需要加-E或者用egrep。

 

 awk精度匹配

查找第一段里包含root的行,以及打印该行第七段

[root@hpf-linux 222]# awk -F':' '$1~/root/ {print $7} ' passwd 

/bin/bash

 查找第一段含有root的行或者第三段大于500的行,打印出行号及全行的内容

[root@hpf-linux 222]# awk -F':' '$1~/root/ || $3>500 {print NR":"$0} ' passwd 
 
1:rootmail:x:0:0:root:/root:/bin/bash
 
22:test2:x:501:501::/home/test2:/bin/bash
 
23:test3:x:502:502::/home/test3:/bin/bash
 
24:mysql:x:503:503::/home/mysql:/sbin/nologin

 查找第一段等于root的行,打印出行号及全行的内容

 

[root@hpf-linux 222]# awk -F':' '$1=="root" {print NR":"$0} ' passwd 

2:root:x:0:0:root:/root:/bin/bash
[root@hpf-linux 222]# awk -F':' 'NR>20 && $3<500 {print NR":"$0} ' passwd 

21:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

22:test1:x:0:0::/home/test1:/bin/bash

 

 6. 表达式与操作符
    表达式是由变量、常量、函数、正则表达式、操作符组成,awk中变量有字符变量和数字变量。如果在awk中定义的变量没有初始化,则初始值为空字串或0。
    注意:字符操作时一定记得需要加引号
    1) 变量定义示例:
        a="welcome to beijing"
        b=12
    2) 操作符(awk操作符与C语言类似)
    +         加
    -         减
    *         乘
    /         除
    %        取余
    ^        幂运算
    ++        自加1
    --        自减1
    +=        相加后赋值给变量(x+=9等同于x=x+9)
    -=        相减后赋值给变量(x-=9等同于x=x-9)
    *=        相乘后赋值给变量(x*=9等同于x=x*9)
    /=        相除后赋值给变量(x/=9等同于x=x/9)
    >        大于
    <        小于
    >=        大于等于
    <=        小于等于
    ==        等于
    !=        不等于
    ~        匹配
    !~        不匹配
    &&        与
    ||        或

 

第七段不等于"/sbin/nologin"的段

[root@hpf-linux 222]# awk -F':' '$7!="/sbin/nologin" {print NR":"$0} ' passwd 

1:rootmail:x:0:0:root:/root:/bin/bash

2:root:x:0:0:root:/root:/bin/bash

7:sync:x:5:0:sync:/sbin:/bin/sync

8:shutdown:x:6:0:shutdowr  tn:/sbin:/sbin/shutdown

9:halt:x:7:0:halt:/sbin:/ro tsbin/halt

22:test1:x:0:0::/home/test1:/bin/bash

23:test2:x:501:501::/home/test2:/bin/bash
 
24:test3:x:502:502::/home/test3:/bin/bash

 第三段小于第四段的行

 [root@hpf-linux 222]# awk -F':' '$3<$4 {print NR":"$0} ' passwd 
 
 5:adm:x:3:4:adm:/varrtoooo/adm:/sbin/nologin
 
 6:lp:x:4:7:lp:/var/sprooootool/lpd:/sbin/nologin
 
 10:mail:x:8:12:mail:/var/spoolroat/mail:/sbin/nologin
 
 1:uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
 
 3:games:x:12:100:games:/usr/games:/sbin/nologin
 
 14:gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
 
 15:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

 第三段与第四段相加并将相加的和输出到第八段

[root@hpf-linux 222]# awk -F':' 'OFS=":",$8=$3+$4 {print NR,$0} ' passwd 
 
1:rootmail:x:0:0:root:/root:/bin/bash:0
 
2:root:x:0:0:root:/root:/bin/bash:0
 
3:bin:x:1:1:bin:/bin:/sbin/nologin:2
 
4:daemon:x:2:2:droataemon:/sbin:/sbin/nologin:4
 
5:adm:x:3:4:adm:/varrtoooo/adm:/sbin/nologin:7
 
6:lp:x:4:7:lp:/var/sprooootool/lpd:/sbin/nologin:11
 
将第三段相加并输出
 [root@hpf-linux 222]# awk -F ':' '{(sum=sum+$3)}; END {print sum}' passwd  
  
 2513

用shell实现 

[root@hpf-linux 222]# sum=0;for i in `awk -F ':' '{print $3}' passwd`;do sum=$[$sum+$i]; done; echo $sum

2513