AWK命令----三剑客之一

一、AWK概念 
    awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输(stdin)、一个或多个文件,或其它命令的输出。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

二、AWK用法
   1、语法格式
        awk [options] 'scripts' var=value file(s)
        awk [options]  -f scriptfile var=value file(s)
   2、常用参数
        -F 指定分隔符(可以是字符串或正则表达式;如-F:)
        -f 从脚本文件中读取awk命令
        -v var=value 赋值变量,将外部变量传递给awk
  3、内置变量 
       ARGC               命令行参数个数
       ARGV               命令行参数排列
       ENVIRON         支持队列中系统环境变量的使用
       FILENAME       awk浏览的文件名
       FNR                 浏览文件的记录数
       FS                   设置输入域分隔符,等价于命令行 -F选项
       NF                   浏览记录的域的个数,执行过程中对应于当前的字段数
       NR                  已读的记录数,相当于行号
       OFS                输出域分隔符
       ORS                输出记录分隔符
       RS                  控制记录分隔符
       $0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。
       $NF是number finally,表示最后一列的信息,跟变量NF是有区别的,变量NF统计的是每行列的总数
  4、常用参数
       -F 指定分隔符(可以是字符串或正则表达式)
       -f 从脚本文件中读取awk命令
       -v var=value 赋值变量,将外部变量传递给awk
  5、AWK模式和操作
      模式
          /正则表达式/:使用通配符的扩展集
          关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试
          模式匹配表达式:用运算符~(匹配)和!~(不匹配)
          BEGIN语句块、pattern语句块、END语句块
      操作
          操作是由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是:变量或数组赋值、输出命令、内置函数、控制流语句
   6、AWK脚本基本结构
       awk 'BEGIN{ print "start" } pattern{ commads } END{ print "end" }' file

三、awk工作原理
    awk 'BEGIN{ commads } pattern{ commads } END{ commads }'
       第一步:执行BEGIN{ commads }语句块的语句
       第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commads }语句块,它逐步扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕
       第三步:当读至输入流末尾时,执行END{ commads }语句块

    BEGIN{ commads }语句块  在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块
    END{ commads }语句块 在awk从输入流中读取完所有的行之后即被执行,它也是一个可选语句块
    pattern{ commads }语句块 中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印读取到的每一行,awk读取的每一行都会执行该语句块

  示例

[root@os test]# awk '/root/' /etc/passwd  #默认是打印读取到的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@os test]# awk -F: '/root/ { print $1,$NF }' /etc/passwd   #以:分隔,打印第一和最后一列
root /bin/bash
operator /sbin/nologin
[root@os test]# echo -e "a line \nb line" | awk 'BEGIN{ print "start" } { print } END{ print "end" }'
start
a line 
b line
end
#统计/etc/passwd文件中每行的字符数
[root@os test]# awk -F "" '{for(i=1;i<=NF;i++) if($i!="\n") ++sum;print sum;a=a+sum;sum=0}END{print "sum:"a}' /etc/passwd

四、外部变量、运算、判断
    1、外部变量,借助 -v选项,可以将外部值传递给awk

[root@os test]# var=10010
[root@os test]# echo | awk -v VARIABLE=$var '{ print VARIABLE }'
10010
[root@os test]# unset var   #撤消变量

    2、运算

类型 运算符 描述
算术运算符 + - 加,减
* / & 乘,除,求余
+ - ! 一元加,减和逻辑非
^*** 求幂
++  -- 增加或减少,作为前缀或后缀
赋值运算符 =、+=、-=、/=、%=、^=、**= 例:a+=5,等价于a=a+5,其它类同
逻辑运算符 ||、&&  逻辑或和逻辑与
关系运算符 <、<=、>、>=、!=、==  
正则运算符 ~、!~ 匹配正则和不匹配正则
其它运算符 条件表达式
$ 字段引用
in 数组中是否存在某键值

 








 

 

 

 

 

 

 

 

 

算术运算示例
[root@os test]# awk 'BEGIN{ a="b";print a++,++a}'
0 2
#注意:所有用作算术运算符进行操作,操作数自动转为数值,所有非操作数值变为0
赋值运算示例
[root@os test]# awk 'BEGIN{ a=4;print a+=5}'
9
[root@os test]# awk 'BEGIN{ a=4;print a*=5}'
20
逻辑运算示例
[root@os test]# awk 'BEGIN{ a=4;b=3;print (a>5 && b<4),(a>5 || b<4)}'
0 1
关系运算示例
[root@os test]# awk 'BEGIN{ a=4;if(a<5){print "ok"}}'
ok
正则运算示例
[root@os test]# awk 'BEGIN{ a="100absfc";if(a ~ /^100/){print "ok"}}'
其它运算示例
[root@os test]# awk 'BEGIN{ a="b";arr[0]="b";arr[1]="c";print (a in arr)}'
0
[root@os test]# awk 'BEGIN{ a="b";arr[0]="b";arr["b"]="c";print (a in arr)}'
1
[root@os test]# awk 'BEGIN{ a=10;print a<9?"ok":"err"}' 
err

五、AWK高级输入输出
    1、读取下一条记录
       awk中next语句使用:在循环逐行匹配,如果遇到next,就会跳过当前行,直接忽略下面语句而进行下一行匹配。多用于多行合并
 

[root@os awktest]# vi test.txt 
a
b
c
d
e
[root@os awktest]# awk 'NR%2==1{next}{print NR,$0}' test.txt 
2 b
4 d

[root@os awktest]# vi next.txt 
httpd       ok
web01[192.168.1.101]
httpd       ok
tomcat      ok
sendmail    ok
web02[192.168.1.102]
httpd       ok
postfix     ok
web03[192.168.1.103]
httpd       ok
mysqld      ok
[root@os awktest]# awk '/^web/{T=$0;next}{print T":\t"$0;}' next.txt 
web01[192.168.1.101]:   httpd       ok
web01[192.168.1.101]:   tomcat      ok
web01[192.168.1.101]:   sendmail    ok
web02[192.168.1.102]:   httpd       ok
web02[192.168.1.102]:   postfix     ok
web03[192.168.1.103]:   httpd       ok
web03[192.168.1.103]:   mysqld      ok

    2、读取一条记录
      awk getline:输出重定向需要使用getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其它输入文件获得输入。它负责从输入获得下一行内容,并给NF,NR,FNR等内置变量赋值。
      用法说明:
         当其左在右无重写向符|或<时,getline作用于当前文件,读入当前文件的第一行给其后缀的变量var或$0,应该注意到,由于awk在处理getline之前已经读入一行,所以getline得到的返回结果是隔行的
         当其左在右有重写向符|或<时,geline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行

[root@os awktest]# awk 'BEGIN{ "date" | getline out; print out }' test
Sat Mar 14 12:06:53 EDT 2020
[root@os awktest]# awk '{ getline } /root/ ' /etc/passwd 
operator:x:11:0:operator:/root:/sbin/nologin     #注意,这里是隔行的,所以只匹配到一个

六、流程控制语句
    在linux awk的while、do-while和for语句中允许使用break,continue语句来控制流程走向,也允许exit语句退出。awk中,流程控制语句,语法结构,与C语言类似。有了这些,很多shell程序都可以交给awk,而且性能非常快
    

 #if语句
[root@os awktest]# awk ' BEGIN{test=100;if(test>90){print "very good"}else if(test>60){print "good"}else{prit "no pass"}}'            
very good

#while语句
[root@os awktest]# awk 'BEGIN{test=13;total=0;while(i<=test){total+=i;i++}print total}'
91   

#for语句(2种格式)                  
[root@os awktest]# awk 'BEGIN{for(k in ENVIRON){print k"="ENVIRON[k];}}'
AWKPATH=.:/usr/share/awk
OLDPWD=/root
SELINUX_LEVEL_REQUESTED=
SELINUX_ROLE_REQUESTED=
......
36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
[root@os awktest]# awk 'BEGIN{for(i=0;i<=13;i++){total+=i}print total;}'
91

七、数组应用
    1、数组的定义
        数字帮数组索引(下标):
         array[1]="sun"
         array[2]="shitou"
        字符串做数组索引(下标):
          array["first"]="www"
          array["last"]="name"
          array["birth"]="1990"

[root@os awktest]# awk 'BEGIN{array[1]="sun";array[2]="shitou";array["first"]="www";array["last"]="name";array["birth"]="1990"; { print array[1] "\n" array["first"]}}'
sun
www
[root@os awktest]# awk 'BEGIN{array[1]="sun";array[2]="shitou";array["first"]="www";array["last"]="name";array["birth"]="1990"; { for(item in array){print array[item]}}}'
1990
www
name
sun
shitou
[root@os awktest]# awk 'BEGIN{array[1]="sun";array[2]="shitou";array["first"]="www";array["last"]="name";array["birth"]="1990"; { for(i=1;i<=2;i++){print array[i]};} }'
sun
shitou

    2、数组相关函数

#输出数组长度
[root@os awktest]# awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA), lens;}'
4 4
#length返回字符串以及数组长度,split进行分割字符串为数组,也会返回分割得到的数组长度



 

你可能感兴趣的:(Linux运维,常用命令)