一、awk概述

  grep、sed与awk,俗称Linux下的三剑客,它们之间有很多相似点,但是同样也各有各的特色。

相似的地方:它们都可以匹配文本,逐行读取数据,支持正则表达式

   其中只有sed可以编辑源文件

   而awk则是一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并格式化输出,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等  

awk:报告生成器,格式化打印

   基于列的文本工具,按行读取文本并视为一条记录,每条记录以指定分割符分割成若干字段,然后输出各字段的值。

   内部支持变量、条件判断、循环、数组

awk --> new awk --> nawk(收费)

GNU awk --> gawk 

   

二、awk的使用

注意:

  awk和默认以任意个空白符为分隔符,而cut默认以制表符为分隔符,而且只能指定以一个字符为分隔符。

   与sed一样使用‘’不要使用""容易报错

   awk只支持ERE,且默认不支持{m,n}加选项 -- posix或者-- re-interval才支持,不支持反向引用:\1,\2,、、、,&等


用法格式:

   awk [OPTIONS] 'SCRIPT' FILE...

   awk [OPTIONS] 'pattern/{action}' File...


1、OPTIONS:

    -F:指定输入文本时所使用的字段分隔符

    -v:自定义变量


2、pattern

包括地址定界:

    /pat1/,/pat2/

    /pattern/

    !/pattern/

    expression: 表达式如:>,<,=,>=,<=,=,!=,==,~

  

3、BEGIN语句

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


4、END语句

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

[root@xxj shell]# awk -F : '/^root/ {print $1}' /etc/passwd
root
[root@xxj shell]# awk -F: '/^\<root\>/ {print $1}' /etc/passwd   
root
[root@xxj shell]# awk -F : '/^root/ {print $1,$7}' /etc/passwd     
                                             #逗号只是命令的一部分,不是输出的结果
root /bin/bash

#使用表达式做定界
[root@Note3 src]# awk -F: '$7='/bin/bash/' {print$1}' /etc/passwd
awk: $7=/bin/bash/ {print$1}
awk:               ^ syntax error
[root@Note3 src]# awk -F: '$3 > 500' /etc/passwd    
                               #不指定输出的字段,则默认输出所有字段
baiyu:x:501:2016::/home/anyfish:/bin/bash
slackware:x:2002:2017::/home/slackware:/bin/tcsh
[root@Note3 src]# awk -F: '$3 > 500 {print $1,$3}' /etc/passwd
baiyu 501
slackware 2002
[root@Note3 src]# awk -F: '$7="/bin/bash/" {print$1}' /etc/passwd
root
bin
daemon
adm
lp
sync

[root@Note3 src]# awk -F: '$7 ~ bash {print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync

BEGIN,END:

[root@xxj shell]# awk -F: '$3>=500 {print "-------------\n"$1}' /etc/passwd 
-------------
testbash
-------------
basher
-------------
nologin
-------------
fedora
-------------
user1
-------------
bash1
-------------
xj
-------------
Oracle
-------------
bash
-------------
xxj
-------------
openstack
-------------
centos

[root@xxj shell]# awk -F: '$3>=500 {print $1}END{print "-------"}' /etc/passwd
testbash
basher
nologin
fedora
user1
bash1
xj
Oracle
bash
xxj
openstack
centos
-------
[root@xxj shell]# awk 'BEGIN{FS=":"} $3>=500 {print $7} ' /etc/passwd
/bin/bash           #用BEGIN指定分隔符
/bin/bash
/sbin/nologin
/bin/bash
/bin/bash
/bin/bash
/bin/bash
/bin/bash
/bin/bash
/bin/bash
/bin/bash
/bin/bash

#BEGIN语句中使用;分隔多个语句
[root@xxj shell]# awk -F: 'BEGIN{print "Username\n----------"}$3>=500 {print $1}' /etc/passwd
Username
----------
testbash
basher
nologin
fedora
user1
bash1
xj
Oracle
bash
xxj
openstack
centos
[root@Note3 ~]# awk 'BEGIN{FS=":";OFS=":"}{print $1,$7}' /etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
shutdown:/sbin/shutdown
halt:/sbin/halt
mail:/sbin/nologin

练习1:

     1、显示GID小于500的组的组名

        # awk -F: '$3<500{print $1}'

     2、显示默认shell为nologin的用户

        # awk -F: '/\<nologin$/ {print $1}'

        # awk -F: '$7=="/sbin/nologin" {print $1}'

     3、显示eh0网卡文件的配置信息,注意只显示=后面的值

        # awk -F= '{print $2}'

     4、显示/etc/sysctl.conf文件中定义的内核参数,只显示名称

        # awk -F= '/^[^#]/ {print $1}'

     5、显示eth0网卡的ip地址,通过Ifconfig的命令结果进行过滤

        # ifconfig eth0|awk -F: '/inet addr/{print $2}'|awk '{print $1}'


5、awk的内置变量

 $1,$2,$3...:第1个字段,第2个字段,第3个字段...

 $0:表示整行

 $NF:表示最后一个字段

 NF:Number of Field,当前记录的field(字段)个数;

 FS: field separator        输入文件本时,所使用字段分隔符;默认空格

 RS:Record separator        输入文本信息所使用的换行符;默认是换行符

 OFS: Output Filed Separator   输出文本时所使用字段分隔符,默认空格,

                               但在语句中要使用逗号(print的使用方法)

 ORS:Output Row Separator    输出文本时所使用行分隔符,默认换行符

 NR: The number of input records,awk命令所处理的行记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;(多各文件一起计数)

 FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中的行数;(多各文件不一起计数)

 ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,

       ARGV[0]保存awk,ARGV[1]保存a.txt;ARGV[2]保存b.txt

 ARGC: awk命令的参数的个数;

 FILENAME: awk命令所处理的文件的名称;在命令中获取当前文件名

 ENVIRON:当前shell环境变量及其值的关联数组;

在awk中引用变量不要加$

[root@Node4 src]# awk 'BEGIN{print 1+1}'
2
[root@Node4 src]# awk 'BEGIN{print 1*1}'
1
[root@Node4 src]# awk 'BEGIN{print 1.01**365}'
37.7834
[root@Node4 src]# awk BEGIN'{print 1.01**365}'
37.7834

[root@Node4 src]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m

[root@Node4 src]# awk '{print NR,NF}' /etc/issue
1 4
2 5
3 0
[root@Node4 src]# awk '{print $NR,$NF}' /etc/issue
CentOS (Final)
\r \m
 
[root@Node4 src]# awk '{print NR,$NF}' /etc/issue /etc/issue
1 (Final)
2 \m
3 
4 (Final)
5 \m
6 

[root@Node4 src]# awk '{print FNR,$NF}' /etc/issue /etc/issue
1 (Final)
2 \m
3 
1 (Final)
2 \m
3 

# ARGV与ARGC
[root@Node4 src]# awk '{print ARGV[0]}' /etc/issue
awk
awk
awk

[root@Node4 src]# awk '{print ARGC}' /etc/issue   # 把{print ARGC}也当作一个参数
2
2
2

6、用户自定义变量

      1)在命令行中使用赋值变量

           在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:

           awk -v var1="str1" -v var2="str2" 'BEGIN{print var1,var2}'

     2)在脚本中赋值变量

         在awk中给变量赋值使用赋值语句进行,例如:

         awk 'BEGIN{var="variable testing";print var}'

     3)将外部变量传递给awk

[root@localhost ~]# awk -v var1=aaa -v var2=bbb 'BEGIN{print var1,var2}'
aaa bbb
[root@localhost ~]# awk -v var1=aaa -v var2=bbb 'BEGIN{print var1 var2}'
aaabbb
[root@localhost ~]# awk 'BEGIN{var1="aaa";var2="bbb";print var1,var2}'
aaa bbb
[root@localhost ~]# var1=aaa
[root@localhost ~]# echo|awk -v x=$var1 '{print x}'
aaa
[root@localhost ~]# var=aaa
[root@localhost ~]# echo|awk '{print x}' x=$var
aaa

7、action

       print,默认打印,不能在bash中单独使用

       printf,用于能够实现格式化输出的工具,

1)print的使用格式

       print item1, item2, ...

   各项目之间使用逗号隔开,而输出时则以空白字符分隔;

   输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;

  print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";


printf命令的使用格式:

        printf "format", item1, item2, ...

要点:

   其与print命令的最大不同是,printf需要指定format;

   format用于指定后面的每个item的输出格式;

  printf语句不会自动打印换行符;\n


format格式的指示符都以%开头,后跟一个字符;如下:

    %c: 显示字符的ASCII码;

%d, %i:十进制整数;

%e, %E:科学计数法显示数值;

   %f: 显示浮点数;

%g,%G: 以科学计数法的格式或浮点数的格式显示数值;

  %s: 显示字符串;

  %u: 无符号整数;

  %%: 显示%自身;


修饰符:

      N: 显示宽度(占多少各字符);

      -: 左对齐;

      +:显示数值符号;

[root@localhost ~]# awk -F: '/root/{print $1,$3}' /etc/passwd
root 0
operator 11
[root@localhost ~]# awk -F: '/root/{print $1$3}' /etc/passwd 
root0
operator11
[root@localhost ~]# awk -F: '/root/{print $1 $3}' /etc/passwd
root0
operator11
[root@localhost ~]# awk -F: '/root/{print}' /etc/passwd      
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# awk -F: '/root/{print ''}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# awk -F: '/root/{print ""}' /etc/passwd   


[root@localhost ~]#

[root@localhost ~]# awk -F: '/root/{printf $1,$3}' /etc/passwd            
rootoperator[root@localhost ~]# 
[root@localhost ~]# awk -F: '/root/{printf "%s%s\n",$1,$3}' /etc/passwd   
root0
operator11
[root@localhost ~]# awk -F: '/root/{printf "%s %s\n",$1,$3}' /etc/passwd
root 0
operator 11
[root@localhost ~]# awk -F: '/root/{printf "%s,%s\n",$1,$3}' /etc/passwd 
root,0
operator,11
[root@localhost ~]# awk -F: '/root/{printf "%s:%s\n",$1,$3}' /etc/passwd 
root:0
operator:11
[root@localhost ~]# awk -F: '/root/{printf "%10s:%s\n",$1,$3}' /etc/passwd
      root:0
  operator:11
[root@localhost ~]# awk -F: '/root/{printf "%-10s:%s\n",$1,$3}' /etc/passwd
root      :0
operator  :11

输出重定向

  print items > output-file

  print items >> output-file

  print items | command

特殊文件描述符:

  /dev/stdin:标准输入

  /dev/sdtout: 标准输出

  /dev/stderr: 错误输出

  /dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;

[root@localhost ~]# awk -F: '/root/{printf "%-10s:%s\n",$1,$3}' /etc/passwd > /dev/null

[root@localhost ~]# awk -F: '/root/{printf "%-10s",$1 > /dev/null}' /etc/passw

8、awk的操作符

算术操作符:

    -x: 负值

    +x: 转换为数值;

   x^y: 

   x**y: 次方

    x*y: 乘法

    x/y:除法

    x+y:

    x-y:

    x%y:

      

字符串操作符:

   只有一个,而且不用写出来,用于实现字符串连接;(空格)


赋值操作符:

 =

 +=

 -=

 *=

 /=

 %=

 ^=

 **=

 ++

 --

注意:如果模式自身是=号,此时使用/=/可能会有语法错误,应以/[=]/替代


比较操作符:

<

<=

>

>=

==

!=

~:模式匹配,左边的字符串能够被右边的模式所匹配为真,否则为假;

!~:


逻辑操作符

&&:与

||:或

   

布尔值

  awk中,任何非0值或非空字符串都为真,反之就为假;(和bash的命令执行状态返回值刚好相反)