awk用法和详细实例

时间:2021-03-30 05:19:45


00x01 awk介绍

   

awk: Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能

有多种版本: New awk(nawk), GNU awk(gawk)

   gawk:模式扫描和处理语言


00x02 awk基本用法


基本用法

awk [options] ‘program’ var=value file…

awk [options] -f programfile var=value file…

awk [options] 'BEGIN{ action;… } pattern{ action;… } END{action;… }' file ...

awk 程序通常由: BEGIN语句块、能够使用模式匹配的通用语句块、 END语句块,共3部分组成

program通常是被单引号或双引号中

   选项:

    -F 指明输入时用到的字段分隔符

    -v var=value: 自定义变量

基本格式:

awk [options] 'program' file…

  program:pattern{action statements;..}

  pattern和action:

pattern部分决定动作语句何时触发及触发事件

BEGIN,END

action statements对数据进行处理,放在{}内指明

print, printf

分割符、域和记录

awk执行时, 由分隔符分隔的字段(域)标记$1,$2..$n称为域标识。 $0为所有域,注意:和shell中变量$符含义不同

文件的每一行称为记录

省略action,则默认执行 print $0 的操作


00x03 awk工作原理


第一步:执行BEGIN{action;… }语句块中的语句

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;…}语句块

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

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

pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行, awk读取的每一行都会执行该语句块


00x04 print


print格式: print item1, item2, ...

  要点:

(1) 逗号分隔符

(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、

变量或awk的表达式

(3) 如省略item,相当于print $0

  示例:

awk '{print "hello,awk"}'

awk �CF: '{print}' /etc/passwd

awk �CF: ‘{print “wang”}’ /etc/passwd

awk �CF: ‘{print $1}’ /etc/passwd

awk �CF: ‘{print $0}’ /etc/passwd

awk �CF: ‘{print $1”\t”$3}’ /etc/passwd

tail �C3 /etc/fstab |awk ‘{print $2,$4}’


00x05 变量


变量:常用内置变量

awk用法和详细实例

 a、FS

 FS field-separator  输入字段分隔符,默认为空白字符

   使用FS的好处就是可以在内部调用这个变量

[root@localhost tmp]# awk -v FS=":" '{print $1,FS,$3}' passwdroot : 0
bin : 1
daemon : 2
adm : 3
lp : 4
sync : 5

[root@localhost tmp]# awk -F ":" '{print $1":"$3}' passwdroot:0bin:1daemon:2adm:3lp:4sync:5

b、OFS

   output field-separator  输出字段分隔符,默认为空白字符

[root@localhost tmp]# awk -v FS=":" -v OFS="$" '{print $1,$3,$7}' passwdroot$0$/bin/bashbin$1$/sbin/nologindaemon$2$/sbin/nologinadm$3$/sbin/nologin


c、RS

    输入记录分隔符,指定输入时的换行符,原换行符仍有效

 

[root@localhost tmp]# awk -v FS=":" -v OFS="$" '{print $1,$3,$7}' passwdnobody:x:99:99:Nobody:/:/sbin/nologinsystemd-bus-proxy:x:999:997:systemdBusProxy:/:/sbin/nologinsystemd-network:x:192:192:systemdNetwork

[root@localhost tmp]# cat testlist a b ddlist2 a2 b2 dd2list4 a3 b3 dd3[root@localhost tmp]# cat test |awk -v RS=" " -v OFS="++" '{print $1,$2}'list++              a++b++  dd++list2               #指定 RS“ ”,dd\nlist2,FS默认为空白字符,$1就是dda2++b2++dd2++list4a3++                                         b3++dd3++

d、 ORS

   输出记录分隔符,输出时用指定符号代替换行符

[root@localhost tmp]# awk -v RS=" " -v ORS="%" '{print}' passwdroot:x:0:0:yemo,62985600:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinsystemd-bus-proxy:x:999:997:systemd%Bus%Proxy:/:/sbin/nologinsystemd-network:x:192:192:systemd%Network%Management:/:/sbin/nologindbus:x:81:81:System%message%bus:/:/sbin/nologinpolkitd:x:998:996:User%for%polkitd:/:/sbin/nologintss:x:59:59:Account%used%by%the%trousers%package%to%sandbox%the%tcsd%daemon:/dev/null:/sbin/nologin

e、 NF

   字段数量

[root@localhost tmp]# cat passwd |awk -F: '{print NF}'   #不需要使用$7777


可以用于循环每行每个字段

[root@localhost tmp]# cat passwd |awk -F: '{for(i=0;i<NF;i++){print $i}}'root:x:0:0:yemo,62985600:/root:/bin/bashrootx00yemo,62985600/rootbin:x:1:1:bin:/bin:/sbin/nologin


f、 NR

  行号

[root@localhost tmp]# cat passwd |awk -F: '{print NR}'1234[root@localhost tmp]# awk 'END{print NR}' passwd22


e、 FNR

  各文件分别计数,行号

[root@localhost tmp]# awk '{print FNR}' /etc/fstab /etc/inittab123456789101112131412...


f、 FILENAME

     当前文件名

[root@localhost tmp]# awk '{print FILENAME}' /etc/fstab/etc/fstab/etc/fstab/etc/fstab/etc/fstab/etc/fstab/etc/fstab


g、 ARGC 

    命令行参数的个数

[root@localhost tmp]# awk 'END{print ARGC}' /etc/fstab /etc/inittab3


h、 ARGV

     数组,保存的是命令行所给定的各参数

[root@localhost tmp]# awk 'END{print ARGV[1]}' /etc/fstab /etc/inittab/etc/fstab[root@localhost tmp]# awk 'END{print ARGV[0]}' /etc/fstab /etc/inittabawk[root@localhost tmp]# awk 'END{print ARGV[2]}' /etc/fstab /etc/inittab/etc/inittab


00x06 自定义变量和环境变量

   自定义变量(区分字符大小写)

(1) -v var=value

(2) 在program中直接定义

[root@localhost tmp]# awk -v a="sh" 'BEGIN{print a}'sh


[root@localhost tmp]# cat awkscript{print script,$1,$2}[root@localhost tmp]# awk -F: -f awkscript script="awk" /etc/passwdawk root x                         #引用文件的变量,相当于已经定义,不用再-v声明awk bin xawk daemon xawk adm xawk lp xawk sync xawk shutdown xawk halt x


环境变量:


awk用法和详细实例


00x07 printf格式化输出


awk用法和详细实例




a、格式printf “FORMAT” , item1, item2, ...

          (1) 必须指定FORMAT

(2) 不会自动换行,需要显式给出换行控制符, \n

(3) FORMAT中需要分别为后面每个item指定格式符

  b、实例

printf '\n'$(tput setaf 2; tput setab 0; tput bold)'background color show'$(tput sgr0)'\n\n'

 awk用法和详细实例

 %s字符串,\t打印tab,\n回车,printf默认不会输出换行符

[root@localhost matrix]# echo "hello world"|awk '{printf "%s\t%s\n",$1,$2}'hello    world


 %d十进制

[root@localhost matrix]# echo "12580 124"|awk '{printf "%d\t%d\n",$1,$2}'12580    124


%o无符号八进制

[root@localhost matrix]# echo "12580 124"|awk '{printf "%o\t%o\n",$1,$2}'30444    174


%x十六进制

[root@localhost matrix]# echo "12580 124"|awk '{printf "%x\t%x\n",$1,$2}'3124    7c


[root@localhost matrix]# awk -F: '{printf "Username: %s,UID:%d\n",$1,$3}' /tmp/passwdUsername: root,UID:0Username: bin,UID:1Username: daemon,UID:2Username: adm,UID:3Username: lp,UID:4


00x08 操作符


算术操作符:

      x+y, x-y, x*y, x/y, x^y, x%y

     -x: 转换为负数

     +x: 转换为数值

[root@localhost matrix]# awk 'BEGIN{print 2-4}'-2[root@localhost matrix]# awk 'BEGIN{print 2^3}'8[root@localhost matrix]# awk -v a=m 'BEGIN{print +a}'0[root@localhost matrix]# awk -v a=m 'BEGIN{print a}'m[root@localhost matrix]# awk -v a=5 'BEGIN{print -a}'-5


字符串拼接

[root@localhost matrix]# awk -v a="hello" -v b="Rie Kugimiya" 'BEGIN{print ab}'[root@localhost matrix]# awk -v a="hello" -v b="Rie Kugimiya" 'BEGIN{print a b}'helloRie Kugimiya


赋值操作符: =, +=, -=, *=, /=, %=, ^=,++, --

[root@localhost matrix]# awk  'BEGIN{b=10;print b}'10[root@localhost matrix]# awk -F: '{for(i=0;i<NF;i++){print i}}' /tmp/passwd01234560123456


比较操作  ==, !=, >, >=, <, <=

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($3>100){print $0}}'systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologinsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologinpolkitd:x:998:996:User for polkitd:/:/sbin/nologinabrt:x:173:173::/etc/abrt:/sbin/nologinyemo:x:1000:1000::/home/yemo:/bin/bash


模式匹配  ~:左边是否和右边匹配包含

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($1 ~/.*oo.*/){print}}'root:x:0:0:yemo,62985600:/root:/bin/bash[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 ~/.*oo.*/){print}}'root:x:0:0:yemo,62985600:/root:/bin/bashlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologinpostfix:x:89:89::/var/spool/postfix:/sbin/nologin


!~:是否不匹配

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 !~/.*oo.*/){print}}'bin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltgames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologinsystemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologinsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologindbus:x:81:81:System message bus:/:/sbin/nologin


逻辑操作符  与&&,或||,非!

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 !~/.*oo.*/ &&$3 >100 ){print}}'systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologinsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologinpolkitd:x:998:996:User for polkitd:/:/sbin/nologinabrt:x:173:173::/etc/abrt:/sbin/nologinyemo:x:1000:1000::/home/yemo:/bin/bash[root@localhost matrix]# awk -F: '!($3>=500) {print $3}' /etc/passwd0123456


函数调用

    自定义函数调用

[root@localhost matrix]# echo "11 22"|awk '{print "max=",max($1,$2)}function max(a,b){if(a>b){return a;}else{return b;}}'max= 22


     内部函数调用

[root@localhost matrix]# echo "ad 12 22 dd"|awk 'split($0,a){for(i in a)printf a[i]}'ddad1222


条件表达式

               三元表达式: selector?if-true-expression:if-false-expression

[root@localhost matrix]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd           root:Sysadmin or SysUser            bin:Sysadmin or SysUser         daemon:Sysadmin or SysUser            adm:Sysadmin or SysUser             lp:Sysadmin or SysUser           sync:Sysadmin or SysUser       shutdown:Sysadmin or SysUser           halt:Sysadmin or SysUser           mail:Sysadmin or SysUser       operator:Sysadmin or SysUser          games:Sysadmin or SysUser            ftp:Sysadmin or SysUser         nobody:Sysadmin or SysUsersystemd-bus-proxy:Sysadmin or SysUsersystemd-network:Sysadmin or SysUser           dbus:Sysadmin or SysUser        polkitd:Sysadmin or SysUser            tss:Sysadmin or SysUser           abrt:Sysadmin or SysUser        postfix:Sysadmin or SysUser           sshd:Sysadmin or SysUser           yemo:Common User


[root@localhost matrix]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%-15s:%-s\n",$1,usertype}' /etc/passwdroot           :Sysadmin or SysUserbin            :Sysadmin or SysUserdaemon         :Sysadmin or SysUseradm            :Sysadmin or SysUserlp             :Sysadmin or SysUsersync           :Sysadmin or SysUsershutdown       :Sysadmin or SysUserhalt           :Sysadmin or SysUsermail           :Sysadmin or SysUser


00x09  PATTERN:根据pattern条件,过滤匹配的行,再做处理


(1)如果未指定:空模式,匹配每一行

[root@localhost tmp]# awk '{print $1}' testlistlist2list4


(2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来

[root@localhost tmp]# cat passwd |awk -F: '/^root\>/ {print }'root:x:0:0:yemo,62985600:/root:/bin/bash                #支持位置铆钉和单词铆钉[root@localhost tmp]# cat passwd |awk -F: '/root/ {print }'   #包含root的全都匹配root:x:0:0:yemo,62985600:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin


(3) relational expression: 关系表达式,结果为“真”才会被处理

真:结果为非0值,非空字符串

     假:结果为空字符串或0值

[root@localhost tmp]# cat passwd |awk -F: 'i=1;j=1{print i,j}'      #i=1后默认有{print $0}root:x:0:0:yemo,62985600:/root:/bin/bash1 1bin:x:1:1:bin:/bin:/sbin/nologin1 1daemon:x:2:2:daemon:/sbin:/sbin/nologin1 1


[root@localhost tmp]# cat passwd |awk -F: '$3>500  {print }'systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologinpolkitd:x:998:996:User for polkitd:/:/sbin/nologinyemo:x:1000:1000::/home/yemo:/bin/bash


匹配finger空的行

[root@localhost tmp]# cat passwd |awk -F: '!$5  {print }'abrt:x:173:173::/etc/abrt:/sbin/nologinpostfix:x:89:89::/var/spool/postfix:/sbin/nologinyemo:x:1000:1000::/home/yemo:/bin/bash


  匹配默认bash是/bin/bash的用户

[root@localhost tmp]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' passwdroot /bin/bashyemo /bin/bash


  匹配 bash结尾

[root@localhost tmp]# awk -F: '$NF ~/bash$/{print $1,$NF}' passwdroot /bin/bashyemo /bin/bash


(4) line ranges: 行范围

             startline,endline: /pat1/,/pat2/ 不支持直接给出数字格式

[root@localhost tmp]# awk -F: '/^root\>/,/^mail\>/{print $1,$3}' passwdroot 0                                                       #类似sed的用法bin 1daemon 2adm 3lp 4sync 5shutdown 6halt 7mail 8


[root@localhost tmp]# awk -F: '(NR>=3&&NR<=10){print $1,$3}' passwddaemon 2adm 3lp 4sync 5shutdown 6halt 7mail 8operator 11


  (5) BEGIN/END模式

                BEGIN{}: 仅在开始处理文件中的文本之前执行一次

                END{}:仅在文本处理完成之后执行一次

[root@localhost tmp]# seq 10|awk ''[root@localhost tmp]# seq 10|awk '1'12345678910[root@localhost tmp]# seq 10|awk '{i=!i;print i}'1010101010[root@localhost tmp]# seq 10|awk '{i=!i}'[root@localhost tmp]# seq 10|awk 'i=0;i=!i'12345678910[root@localhost tmp]# seq 10|awk 'i=1;i=!i'12345678910[root@localhost tmp]# seq 10|awk -v i=1 'i=!i'246810[root@localhost tmp]# seq 10|awk '!(i=!i)'246810


00x0a action


awk用法和详细实例


00x0b 控制语句



awk用法和详细实例


 1)if循环

       if(condition){statement;…}[else statement]

[root@localhost tmp]# cat passwd |awk -F: '{if($3>500){print}}'systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologinpolkitd:x:998:996:User for polkitd:/:/sbin/nologinyemo:x:1000:1000::/home/yemo:/bin/bash


[root@localhost tmp]# cat passwd |awk -F: '{if($NF=="/bin/bash"){print}}'root:x:0:0:yemo,62985600:/root:/bin/bashyemo:x:1000:1000::/home/yemo:/bin/bash


[root@localhost tmp]# cat passwd |awk -F: '{if($5!=""){print}}'root:x:0:0:yemo,62985600:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost tmp]# cat passwd |awk -F: '{if($3>500){printf "commusr:%s\n",$1}else{printf "sysuser:%s\n",$1 }}'sysuser:rootsysuser:binsysuser:daemonsysuser:admsysuser:gamessysuser:ftpsysuser:nobodycommusr:systemd-bus-proxysysuser:systemd-networksysuser:dbuscommusr:polkitdsysuser:tsssysuser:abrtsysuser:postfixsysuser:sshdcommusr:yemo


[root@localhost tmp]# df -P|awk -F "% " '/dev\/sd/ {print}'|awk '{if($5>3)printf "%s\t%s\n",$1,$5}'/dev/sda2    4%/dev/sda1    3%


      if(condition1){statement1}else if(condition2){statement2}else{statement3}

[root@localhost tmp]# echo "10 99 100 60 50"|awk '{for(i=1;i<(NF+1);i++) {if($i>=90){print $i,"verygood";}else if($i>=60&&$i<90){print $i,"is ok";}else {print $i"you are too low"} }}'10you are too low99 verygood100 verygood60 is ok50you are too low


      while循环

语法: while(condition){statement;…}

 条件“真”,进入循环;条件“假”, 退出循环

 使用场景:

对一行内的多个字段逐一类似处理时使用

对数组中的各元素逐一处理时使用

[root@localhost tmp]# awk '/^\s*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfglinux16 7/vmlinuz-3.10.0-514.el7.x86_64 30root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46ro 2crashkernel=auto 16rhgb 4quiet 5LANG=en_US.UTF-8 16net.ifnames=0 13


[root@localhost tmp]# awk '/^\s*linux16/{i=1;while(i<=NF){if(length($i)>10){print $i,length($i)};i++ } }' /etc/grub2.cfg/vmlinuz-3.10.0-514.el7.x86_64 30root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46crashkernel=auto 16LANG=en_US.UTF-8 16net.ifnames=0 13/vmlinuz-0-rescue-8665dcc4833c41eaa11fa716f7dcd792 50root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46crashkernel=auto 16


do-while循环

语法: do {statement;…}while(condition)

意义:无论真假,至少执行一次循环体

[root@localhost tmp]# awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}'5050[root@localhost tmp]# awk 'BEGIN{total=1;i=1;do{total+=i;i++;}while(i<=0);print total}'2
[root@localhost tmp]# awk 'BEGIN{i=0;print ++i,i}'          #先加后赋值1 1[root@localhost tmp]# awk 'BEGIN{i=0;print i++,i}'          #先赋值在加0 1

  for循环

     语法:for(expr1;expr2;expr3) {statement;…}

常见用法:

          for(variable assignment;condition;iteration process){for-body}

特殊用法:能够遍历数组中的元素

echo "10 99 100 60 50"|awk '{for(i=1;i<(NF+1);i++) {if($i>=90){print $i,"verygood";}else if($i>=60&&$i<90){print $i,"is ok";}else {print $i"you are too low"} }}'10you are too low99 verygood100 verygood60 is ok50you are too low


[root@localhost tmp]# cat access.log |awk '{++arr[$1]}{for(i in arr){print i,arr[i]}}'192.168.1.44 34172.16.100.76 204192.168.1.100 12192.168.1.101 1192.168.1.110 83192.168.99.72 18172.16.100.125 18127.0.0.1 7192.168.1.121 13192.168.1.112 27172.16.0.100 4172.16.100.126 3192.168.1.113 583172.16.23.100 14192.168.1.114 12192.168.6.1 42172.16.250.227 68192.168.1.106 22172.16.233.133 112192.168.1.107 68192.168.1.108 3

switch语句

      语法: switch(expression) {case VALUE1 or /REGEXP/:statement1; case VALUE2 or /REGEXP2/: statement2;...; default: statementn}

           break和continue

         

[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<=100;i++){if(i%2==0)continue;sum+=i}print sum  }'2500

 

[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<=100;i++){if(i==55)break;sum+=i}print sum  }'1485
[root@localhost ~]# awk -F: '{if($3%2!=0)next;print $1,$3}' /tmp/passwdroot 0daemon 2lp 4shutdown 6mail 8games 12ftp 14systemd-network 192polkitd 998sshd 74yemo 1000


   00x0b  awk数组

     a)  关联数组: array[index-expression]

     index-expression:

(1) 可使用任意字符串;字符串要使用双引号括起来

(2) 如果某数组元素事先不存在,在引用时, awk会自动创建此元素,并将其值初始化为“空串”

若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

     若要遍历数组中的每个元素,要使用for循环

  for(var in array) {for-body}

  注意: var会遍历array的每个索引

[root@localhost tmp]# cat access.log |awk '{++arr[$1]}{for(i in arr){print i,arr[i]}}'192.168.1.44 34172.16.100.76 204192.168.1.100 12192.168.1.101 1192.168.1.110 83192.168.99.72 18172.16.100.125 18127.0.0.1 7192.168.1.121 13192.168.1.112 27172.16.0.100 4172.16.100.126 3192.168.1.113 583172.16.23.100 14192.168.1.114 12192.168.6.1 42172.16.250.227 68192.168.1.106 22172.16.233.133 112192.168.1.107 68192.168.1.108 3

 使用关联数组对重复IP地址计数,以IP地址为索引,出现相同索引的就自加,达到计数的目的,数组缺省值为0。


00x0c 函数


     a)内置函数

          

awk用法和详细实例


 01  sub函数匹配记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配的时候。

               sub (regular expression, substitution string):

                sub (regular expression, substitution string, target string)

[root@localhost tmp]# awk '{sub(/a/,"test");print}' testlisttest a ba dadlisttest2 a2 ba2 dad2listtest4 a3 ba3 dad3[root@localhost tmp]# cat testlista a ba dadlista2 a2 ba2 dad2lista4 a3 ba3 dad3

02   gsub函数作用如sub,但它在整个文档中进行匹配。

[root@localhost tmp]# awk '{gsub(/a/,"test");print}' testlisttest test btest dtestdlisttest2 test2 btest2 dtestd2listtest4 test3 btest3 dtestd3


03   index  函数返回子字符串第一次被匹配的位置,偏移量从位置1开始。

                  index(string, substring)


04  substr函数返回从位置1开始的子字符串,如果指定长度超过实际长度,就返回整个字符串。

                substr( string, starting position )

                 substr( string, starting position, length of string )


05   split函数可按给定的分隔符把字符串分割为一个数组。如果分隔符没提供,则按当前FS值进行分割。

              split( string, array, field separator )

               split( string, array )


06  length函数返回记录的字符数。

               length( string )

                length


07 match函数返回在字符串中正则表达式位置的索引,如果找不到指定的正则表达式则返回0。match函数会设置内建变量RSTART为字符串中子字符串的开始位置,RLENGTH为到子字符串末尾的字符个数。substr可利于这些变量来截取字符串。

                 match( string, regular expression )


08  toupper和tolower函数可用于字符串大小间的转换,该功能只在gawk中有效。

                     toupper( string )

                     tolower( string )



  b) 数学函数 

awk用法和详细实例

00x0d 通过system调用系统命令

           空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。

[root@localhost ~]# awk 'BEGIN{system("hostname")}'localhost.localdomain[root@localhost ~]# awk 'BEGIN{s=100;system("echo your score is" s)}'your score is100[root@localhost ~]# awk 'BEGIN{s=100;system("echo your score is " s)}'your score is 100


00x0e 创建awk脚本

[root@localhost tmp]# vim tstawk.awk[root@localhost tmp]# cat tstawk.awk#!/bin/awk -f{if($3>=1000)print $1,$3}[root@localhost tmp]# awk -F: -f tstawk.awk passwdyemo 1000
[root@localhost tmp]# chmod +x tst2.awk[root@localhost tmp]# cat tst2.awk#!/bin/awk -f{if($3>=1000)print $1,$3}[root@localhost tmp]# ./tst2.awk  -F: passwdyemo 1000


向awk脚本传递参数

           格式:

                    awkfile var=value var2=value2... Inputfile

     注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v 参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数

[root@localhost tmp]# cat tst2.awk#!/bin/awk -f{if($3>=min && $3<=max)print $1,$3}[root@localhost tmp]# ./tst2.awk -F: min=100 max=500 passwdsystemd-network 192abrt 173


实例:

对fstab文件取单词并计数排序

[root@localhost tmp]# cat /etc/fstab |tr "[:punct:]"  " " |awk '{split($0,arr," ");for(i in arr){brr[arr[i]]++ }} END{for(k in brr){print brr[k],k}} '|sort -nr6 UUID6 defaults5 xfs3 82 swap2 fstab2 by1 Wed1 var1 under1 See1 reference1 pages

提取字符串中数字

[root@localhost tmp]# echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk -F "[^[:digit:]]" '{for(i=1;i<=NF;i++){printf "%s",$i}}'05973


[root@localhost tmp]# ss -ntl|awk -F "[ :]" '/^[^S]/ {arr[$6]++}END{for(i in arr){print arr[$i],i}}'|sort -nr


去掉一个最高一个最低求平均值

冯泉    100     100     96      95      100     96      100     97万永振  100     95      90      88      95      98      95      98徐亮��  100     100     90      98      90      98      100     96曹雅楠  100     100     95      90      97      90      95      98陈派宇  90      95      95      96      100     98      100     96李峰    90      90      90      85      92      95      95      98余连辉  90      93      95      92      95      95      96      95侯亚光  90      96      97      90      90      85      95      90王续    85      92      98      98      90      95蔚雷    92      92      96      90      90      80苏浩智  88      96      85      95      90      90徐登辉  85      95      88      90      90      90林章益  91      97      98      90      100     90黄品清  85      97      88      90      90      90李健    85      95      90      88      80      80宫全乐  88      95      90      88      90      100万良    89      95      95      88      100     100马自强  88      97      90      88      90      90任冠亚  88      97      98      90      100     100

解法1

[root@localhost tmp]# cat awk_tst.tst |awk '{for(i=2;i<=NF;i++){a[i]=$i};sum=0;tmp=0;for(j in a){for(k in a){if(a[k]>a[j]){tmp=a[k];a[k]=a[j];a[j]=tmp;}}}for(s=2;s<length(a);s++){sum+=a[s]};arr=sum/(length(a)-2);print $1,arr;delete a}'


本文出自 “庭前夜末空看雪” 博客,请务必保留此出处http://12550795.blog.51cto.com/12540795/1966558